# t/protocol.t # # Test LJ::Protocol. # # Authors: # Catness # # Copyright (c) 2013 by Dreamwidth Studios, LLC. # # This program is free software; you may redistribute it and/or modify it under # the same terms as Perl itself. For a copy of the license, please reference # 'perldoc perlartistic' or 'perldoc perlgpl'. # use strict; use warnings; use Test::More skip_all => "Test is not deterministic -- inconsistent results from content filters"; #tests => 243; BEGIN { $LJ::_T_CONFIG = 1; require "$ENV{LJHOME}/cgi-bin/ljlib.pl"; } use LJ::Protocol; use DW::Pay; use LJ::Test qw( temp_user temp_comm ); no warnings "once"; my $u = temp_user(); my $watched = temp_user(); my $trusted = temp_user(); my $watchedtrusted = temp_user(); my $comm = temp_comm(); my $watcher = temp_user(); my $truster = temp_user(); my $watchertruster = temp_user(); my @watched = ( $watched, $watchedtrusted, $comm ); my @trusted = ( $trusted, $watchedtrusted ); my @watchedby = ( $watcher, $watchertruster ); my @trustedby = ( $truster, $watchertruster ); $u->add_edge( $_, watch => { nonotify => 1 } ) foreach @watched; $u->add_edge( $_, trust => { nonotify => 1 } ) foreach @trusted; $_->add_edge( $u, watch => { nonotify => 1 } ) foreach @watchedby; $_->add_edge( $u, trust => { nonotify => 1 } ) foreach @trustedby; my $err = 0; my $res = {}; my $do_request = sub { my ( $mode, %request_args ) = @_; my $err = 0; my %flags = %{ delete $request_args{flags} || {} }; my $req = \%request_args; my $res = LJ::Protocol::do_request( $mode, $req, \$err, { noauth => 1, %flags } ); return ( $res, $err ); }; my $check_err = sub { local $Test::Builder::Level = $Test::Builder::Level + 1; my ( $expectedcode, $testmsg ) = @_; # code is either in the form of ###, or ###:description like( $err, qr/^$expectedcode(?:$|[:])/, "$testmsg Protocol error ($err) = " . LJ::Protocol::error_message($err) ); }; my $success = sub { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($testmsg) = @_; is( $err, 0, "$testmsg (success)" ); }; note("getfriendgroups"); { ( $res, $err ) = $do_request->("getfriendgroups"); $check_err->( 504, "'getfriendgroups' is deprecated." ); is( $res, undef, "No response expected." ); ( $res, $err ) = $do_request->( "getfriendgroups", username => $u->user ); $check_err->( 504, "'getfriendgroups' is deprecated." ); is( $res, undef, "No response expected." ); } note("gettrustgroups"); { # test arguments: # username ( $res, $err ) = $do_request->("gettrustgroups"); $check_err->( 200, "'gettrustgroups' needs a user." ); is( $res, undef, "No response expected." ); ( $res, $err ) = $do_request->( "gettrustgroups", username => $u->user ); $success->("'gettrustgroups' for user."); ok( ref $res->{trustgroups} eq "ARRAY" && scalar @{ $res->{trustgroups} } == 0, "Empty trust groups list." ); }; note("getcircle"); { # test arguments: # username # limit # includetrustgroups # includecontentfilters # includewatchedusers # includewatchedby # includetrustedusers ( $res, $err ) = $do_request->("getcircle"); $check_err->( 200, "'getcircle' needs a user." ); is( $res, undef, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user ); $success->("'getcircle' for user."); is( scalar keys %$res, 0, "Empty circle; no arguments provided to select the subset of the circle." ); my %circle_args = ( # request hash key => response hash key, users includewatchedby => [ "watchedbys", \@watchedby ], includetrustedby => [ "trustedbys", \@trustedby ], includewatchedusers => [ "watchedusers", \@watched ], includetrustedusers => [ "trustedusers", \@trusted ], ); while ( my ( $include, $val ) = each %circle_args ) { ( $res, $err ) = $do_request->( "getcircle", username => $u->user, $include => 1 ); $success->("'getcircle' => $include"); is( scalar keys %$res, 1, "One key: " . ( keys %$res )[0] ); is( ref $res->{ $val->[0] }, "ARRAY", "Returned an arrayref of this user's $include." ); my @cached_users = @{ $val->[1] }; my @response_users = @{ $res->{ $val->[0] } }; is( scalar @response_users, scalar @cached_users, "Matched the number of users who are watching/trusting." ); # check both ways that the users we added are the users we got back my %cached_users = map { $_->user => 0 } @cached_users; foreach my $user (@response_users) { ok( ++$cached_users{ $user->{username} }, "User from response is expected to be there." ); } ok( $cached_users{$_}, "User appeared in the response." ) foreach keys %cached_users; } # set a limit, and check against that my $old_limit = $LJ::MAX_WT_EDGES_LOAD; $LJ::MAX_WT_EDGES_LOAD = 2; while ( my ( $include, $val ) = each %circle_args ) { my @cached_users = @{ $val->[1] }; my $limit = scalar @cached_users > $LJ::MAX_WT_EDGES_LOAD ? $LJ::MAX_WT_EDGES_LOAD : scalar @cached_users; ( $res, $err ) = $do_request->( "getcircle", username => $u->user, $include => 1, limit => $LJ::MAX_WT_EDGES_LOAD + 1 ); $success->("'getcircle' => $include"); # check that the users we got back are from the users we added # don't check the other way, since we are over limit my @response_users = @{ $res->{ $val->[0] } }; is( scalar @response_users, $limit, "Check that the number of users who can be fetched is limited." ); my %cached_users = map { $_->user => 0 } @cached_users; foreach my $user (@response_users) { ok( ++$cached_users{ $user->{username} }, "User from response is expected to be there." ); } } ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includetrustgroups => 1 ); $success->("'getcircle' => includetrustgroups"); is( scalar keys %$res, 1, "One key: " . ( keys %$res )[0] ); ok( ref $res->{trustgroups} eq "ARRAY" && scalar @{ $res->{trustgroups} } == 0, "Empty trust groups list." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); $success->("'getcircle' => includecontentfilters"); is( scalar keys %$res, 1, "One key: " . ( keys %$res )[0] ); ok( ref $res->{contentfilters} eq "ARRAY" && scalar @{ $res->{contentfilters} } == 0, "Empty list of content filters for this user." ); $LJ::MAX_WT_EDGES_LOAD = $old_limit; } note("editcircle"); { # test arguments: # settrustgroups # deletetrustgroups # setcontentfilters # deletecontentfilters # add # addtocontentfilters # deletefromcontentfilters ( $res, $err ) = $do_request->( "editcircle", settrustgroups => 1 ); $check_err->( 200, "'editcircle' needs a user." ); is( $res, undef, "No response expected." ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, settrustgroups => 1 ); $success->("No valid action provided for editcircle; ignore."); is( scalar keys %$res, 0, "No action taken." ); my %trustgroups = ( 1 => { name => "first", sort => 1, public => 0 }, 5 => { name => "incomplete" }, 10 => { # no name? } ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, settrustgroups => \%trustgroups ); $success->("Set trust groups."); is( scalar keys %$res, 0, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includetrustgroups => 1 ); is( scalar @{ $res->{trustgroups} }, scalar keys %trustgroups, "Number of trust groups match." ); foreach my $trustgroup ( @{ $res->{trustgroups} } ) { my $id = $trustgroup->{id}; my $orig_trustgroup = $trustgroups{$id}; is( $trustgroup->{name}, $orig_trustgroup->{name} || "", "Trustgroup name matches." ); is( $trustgroup->{public}, $orig_trustgroup->{public} || 0, "Trustgroup public setting matches." ); is( $trustgroup->{sortorder}, $orig_trustgroup->{sort} || 50, "Trustgroup sortorder matches." ); } # then edit one trust group, and add another my $edited = { name => "hasname", sortorder => 20, public => 1, }; $trustgroups{10} = $edited; my $new = { name => "new", }; $trustgroups{20} = $new; ( $res, $err ) = $do_request->( "editcircle", username => $u->user, settrustgroups => { 10 => $edited, 20 => $new } ); $success->("Edited trust groups; those not mentioned should not be affected."); is( scalar keys %$res, 0, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includetrustgroups => 1 ); is( scalar @{ $res->{trustgroups} }, scalar keys %trustgroups, "Number of trust groups match." ); foreach my $trustgroup ( @{ $res->{trustgroups} } ) { my $id = $trustgroup->{id}; my $orig_trustgroup = $trustgroups{$id}; is( $trustgroup->{name}, $orig_trustgroup->{name} || "", "Trustgroup name matches." ); is( $trustgroup->{public}, $orig_trustgroup->{public} || 0, "Trustgroup public setting matches." ); is( $trustgroup->{sortorder}, $orig_trustgroup->{sort} || 50, "Trustgroup sortorder matches." ); } # then delete some trust groups delete $trustgroups{5}; delete $trustgroups{10}; ( $res, $err ) = $do_request->( "editcircle", username => $u->user, deletetrustgroups => [ 10, 5 ] ); $success->("Deleted a trust group."); is( scalar keys %$res, 0, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includetrustgroups => 1 ); is( scalar @{ $res->{trustgroups} }, scalar keys %trustgroups, "Number of trust groups match." ); foreach my $trustgroup ( @{ $res->{trustgroups} } ) { my $id = $trustgroup->{id}; my $orig_trustgroup = $trustgroups{$id}; is( $trustgroup->{name}, $orig_trustgroup->{name} || "", "Trustgroup name matches." ); is( $trustgroup->{public}, $orig_trustgroup->{public} || 0, "Trustgroup public setting matches." ); is( $trustgroup->{sortorder}, $orig_trustgroup->{sort} || 50, "Trustgroup sortorder matches." ); } # now add / edit some users' status in your circle ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => "invalidusername" } ] ); $check_err->( 203, "Tried to edit invalid user." ); is( scalar keys %$res, 0, "No response expected." ); # let's make our watch/trust mutual # ... but not yet ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user } ] ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includewatchedusers => 1, includetrustedusers => 1 ); is( scalar @{ $res->{watchedusers} }, scalar @watched, "Number of watched users did not change." ); is( scalar @{ $res->{trustedusers} }, scalar @trusted, "Number of trusted users did not change." ); # add with trust group is( $u->trustmask($watchertruster), 0, "Currently not trusted." ); ok( !$u->trusts($watchertruster), "Currently not trusted." ); ok( !$u->watches($watchertruster), "Currently not watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user, groupmask => 201 } ] ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includewatchedusers => 1, includetrustedusers => 1 ); is( scalar @{ $res->{watchedusers} }, scalar @watched, "Number of watched users did not change." ); is( scalar @{ $res->{trustedusers} }, scalar @trusted + 1, "Trusted this user." ); is( $u->trustmask($watchertruster), 201, "Trusted, with trust group that matches." ); ok( $u->trusts($watchertruster), "Currently trusted." ); ok( !$u->watches($watchertruster), "Currently not watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); # add and remove ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user, edge => 0b00 } ] ); is( $u->trustmask($watchertruster), 0, "Not trusted." ); ok( !$u->trusts($watchertruster), "Currently not trusted." ); ok( !$u->watches($watchertruster), "Currently not watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user, edge => 0b01 } ] ); is( $u->trustmask($watchertruster), 1, "Just trust." ); ok( $u->trusts($watchertruster), "Currently trusted." ); ok( !$u->watches($watchertruster), "Currently not watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user, edge => 0b10 } ] ); is( $u->trustmask($watchertruster), 0, "Not trusted." ); ok( !$u->trusts($watchertruster), "Currently not trusted." ); ok( $u->watches($watchertruster), "Currently watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user, edge => 0b11 } ] ); is( $u->trustmask($watchertruster), 1, "Just trust." ); ok( $u->trusts($watchertruster), "Currently trusted." ); ok( $u->watches($watchertruster), "Currently watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); # edit again with groupmask, after already having created a trust mask ( $res, $err ) = $do_request->( "editcircle", username => $u->user, add => [ { username => $watchertruster->user, groupmask => 201 } ] ); is( $u->trustmask($watchertruster), 201, "Trusted, with trust group that matches." ); ok( $u->trusts($watchertruster), "Currently trusted." ); ok( $u->watches($watchertruster), "Currently watched." ); ok( $watchertruster->trusts($u), "Trusted by." ); ok( $watchertruster->watches($u), "Watched by." ); # now to my %contentfilters = ( 1 => { name => "first", sort => 1, public => 0 }, 2 => { name => "incomplete" }, ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, setcontentfilters => \%contentfilters ); $success->("Set content filters."); is( scalar keys %$res, 1, "Response contains only the newly added content filters." ); # FIXME (1/3): this sometimes returns 1 instead of 2 is( scalar @{ $res->{addedcontentfilters} }, scalar keys %contentfilters, "Got back the newly-added content filters." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); # FIXME (2/3): this sometimes returns 1 instead of 2 is( scalar @{ $res->{contentfilters} }, scalar keys %contentfilters, "Number of content filters match." ); foreach my $filter ( @{ $res->{contentfilters} } ) { my $id = $filter->{id}; my $orig_filter = $contentfilters{$id}; is( $filter->{name}, $orig_filter->{name} || "", "Filter name matches." ); is( $filter->{public}, $orig_filter->{public} || 0, "Filter public setting matches." ); is( $filter->{sortorder}, $orig_filter->{sort} || 0, "Filter sortorder matches." ); } # then edit one filter, and add another $edited = { name => "not so incomplete", sortorder => 20, public => 1, }; $contentfilters{2} = $edited; $new = { name => "new", }; $contentfilters{3} = $new; ( $res, $err ) = $do_request->( "editcircle", username => $u->user, setcontentfilters => { 2 => $edited, 3 => $new } ); $success->("Edited content filters; those not mentioned should not be affected."); is( scalar keys %$res, 1, "Response contains only the newly added content filters." ); is( scalar @{ $res->{addedcontentfilters} }, 1, "Got back the newly-added content filter." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); # FIXME (3/3): this sometimes returns 2 instead of 3 is( scalar @{ $res->{contentfilters} }, scalar keys %contentfilters, "Number of content filters match." ); foreach my $filter ( @{ $res->{contentfilters} } ) { my $id = $filter->{id}; my $orig_filter = $contentfilters{$id}; is( $filter->{name}, $orig_filter->{name} || "", "Filter name matches." ); is( $filter->{public}, $orig_filter->{public} || 0, "Filter public setting matches." ); is( $filter->{sortorder}, $orig_filter->{sort} || 0, "Filter sortorder matches." ); } # then delete some content filters delete $contentfilters{1}; delete $contentfilters{3}; ( $res, $err ) = $do_request->( "editcircle", username => $u->user, deletecontentfilters => [ 1, 3 ] ); $success->("Deleted content filters."); is( scalar keys %$res, 0, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); is( scalar @{ $res->{contentfilters} }, scalar keys %contentfilters, "Number of content filters match." ); foreach my $filter ( @{ $res->{contentfilters} } ) { my $id = $filter->{id}; my $orig_filter = $contentfilters{$id}; is( $filter->{name}, $orig_filter->{name} || "", "Filter name matches." ); is( $filter->{public}, $orig_filter->{public} || 0, "Filter public setting matches." ); is( $filter->{sortorder}, $orig_filter->{sort} || 0, "Filter sortorder matches." ); } ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); ok( $res->{contentfilters}->[0]->{data} eq "", "No data for the content filter." ); # added non-existent user ( $res, $err ) = $do_request->( "editcircle", username => $u->user, addtocontentfilters => [ { username => "invalid_user", id => 2 } ] ); $check_err->( 203, "Tried to add an invalid user to a content filter." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); ok( $res->{contentfilters}->[0]->{data} eq "", "No data for the content filter." ); # added a valid user ( $res, $err ) = $do_request->( "editcircle", username => $u->user, addtocontentfilters => [ { username => $watched->user, id => 2 } ] ); $success->("Added a user to a content filter."); is( scalar keys %$res, 0, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); ok( $res->{contentfilters}->[0]->{data} ne "", "Some data in the content filter." ); # tried to remove a non-existent user ( $res, $err ) = $do_request->( "editcircle", username => $u->user, deletefromcontentfilters => [ { username => "invalid_user", id => 2 } ] ); $check_err->( 203, "Tried to remove an invalid user from a content filter." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); ok( $res->{contentfilters}->[0]->{data} ne "", "Some data in the content filter." ); # tried to remove a valid user, but one not in the content filter ( $res, $err ) = $do_request->( "editcircle", username => $u->user, deletefromcontentfilters => [ { username => $watchedtrusted->user, id => 2 } ] ); $success->("Tried to remove a user who was not in the content filter."); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); ok( $res->{contentfilters}->[0]->{data} ne "", "Some data in the content filter." ); ( $res, $err ) = $do_request->( "editcircle", username => $u->user, deletefromcontentfilters => [ { username => $watched->user, id => 2 } ] ); $success->("Removed a user from a content filter."); is( scalar keys %$res, 0, "No response expected." ); ( $res, $err ) = $do_request->( "getcircle", username => $u->user, includecontentfilters => 1 ); ok( $res->{contentfilters}->[0]->{data} eq "", "No more data in the content filter." ); } note("post to community by various journaltypes"); { # test cases: # personal journal posting to a community # community posting to a community # openid account posting to a community # open up community posting to everybody my $admin = temp_user(); $admin->join_community( $comm, 1, 1 ); LJ::set_rel( $comm->userid, $admin->userid, "A" ); delete $LJ::REQ_CACHE_REL{ $comm->userid . "-" . $admin->userid . "-A" }; # to be safe $comm->set_comm_settings( $admin, { membership => "open", postlevel => "members" } ); $comm->set_prop( nonmember_posting => 1 ); # validate the user, so they can post LJ::update_user( $u, { status => 'A' } ); ( $res, $err ) = $do_request->( "postevent", username => $u->user, usejournal => $comm->user, event => "new test post to community", tz => "guess", ); $success->("Entry posted successfully to community by personal journal."); my $comm2 = temp_comm(); ( $res, $err ) = $do_request->( "postevent", username => $comm2->user, usejournal => $comm->user, event => "new test post to community by community2" ); $check_err->( 300, "Communities cannot post entries." ); ( $res, $err ) = $do_request->( "postevent", username => $comm->user, usejournal => $comm->user, event => "new test post to self by a community", tz => "guess", ); $check_err->( 300, "Communities cannot post entries, not even to themselves." ); # openid cases my $identity_u = temp_user( journaltype => "I" ); $identity_u->update_self( { status => "A" } ); # allow all users to add and control tags (for convenience) $comm->set_prop( opt_tagpermissions => "public,public" ); # allow identity users to post entries and add / control tags ok( LJ::Tags::can_control_tags( $comm, $identity_u ), "Identity user can control tags on communities." ); ok( LJ::Tags::can_add_tags( $comm, $identity_u ), "Identity user can control tags on communities." ); ( $res, $err ) = $do_request->( "postevent", username => $identity_u->user, usejournal => $comm->user, event => "new test post to a community by an identity user (no tags)", tz => "guess", ); $success->("OpenID users can post entries to communities."); ( $res, $err ) = $do_request->( "postevent", username => $identity_u->user, usejournal => $comm->user, event => "new test post to a community by an identity user (with tags)", props => { taglist => "testing" }, tz => "guess", ); $success->("OpenID users can post entries including tags to communities."); } # Bug 3271 note("editing an entry with existing tags, when only admins can edit tags"); { my $u = temp_user(); my $admin = temp_user(); my $comm = temp_comm(); ## SETUP $admin->join_community( $comm, 1, 1 ); LJ::set_rel( $comm->userid, $admin->userid, "A" ); delete $LJ::REQ_CACHE_REL{ $comm->userid . "-" . $admin->userid . "-A" }; # to be safe $comm->set_comm_settings( $admin, { membership => "open", postlevel => "members" } ); $comm->set_prop( nonmember_posting => 1 ); # restrict so that only admins can edit tags $comm->set_prop( opt_tagpermissions => "private,private" ); # validate the user, so they can post LJ::update_user( $u, { status => 'A' } ); ## TEST # post entry with tags... ( $res, $err ) = $do_request->( "postevent", username => $u->user, usejournal => $comm->user, event => "new test post to a community containing tags when you're not allowed to have them", props => { taglist => "user-tag" }, tz => "guess", ); $check_err->( 312, "Can't add tags to entries in this community" ); # post entry with no tags ( $res, $err ) = $do_request->( "postevent", username => $u->user, usejournal => $comm->user, event => "new test post to a community this time with no tags", tz => "guess", ); $success->("entry posted successfully"); my $itemid = $res->{itemid}; # admin adds tags LJ::Tags::update_logtags( $comm, $itemid, { set_string => "admin-tag", remote => $admin, } ); my $entry = LJ::Entry->new( $comm, jitemid => $itemid ); is_deeply( [ $entry->tags ], [qw( admin-tag )], "yes, admin added tags successfully" ); # try to edit entry (editing tags) ( $res, $err ) = $do_request->( "editevent", username => $u->user, usejournal => $comm->user, itemid => $entry->jitemid, ver => 1, event => "new entry text lalala", props => { taglist => "admin-tag, user-tag" }, ); is( $res->{message}, "You are not allowed to tag entries in this journal.", "warning given because we can't edit the tags" ); LJ::start_request(); $entry = LJ::Entry->new( $comm, jitemid => $itemid ); is( $entry->event_raw, "new entry text lalala", "BUT entry text was edited" ); is_deeply( [ $entry->tags ], [qw( admin-tag )], "did not touch the tags" ); # try to edit entry (original tags) ( $res, $err ) = $do_request->( "editevent", username => $u->user, usejournal => $comm->user, itemid => $itemid, ver => 1, event => "new entry text (again) lalala", props => { taglist => "admin-tag", }, ); $success->("edited entry successfully"); LJ::start_request(); $entry = LJ::Entry->new( $comm, jitemid => $itemid ); is( $entry->event_raw, "new entry text (again) lalala", "entry text edited" ); is_deeply( [ $entry->tags ], [qw( admin-tag )], "did not touch the tags" ); } note("checkforupdates"); { my $u = temp_user(); my $start = 0; my $end = 15; # make sure no one can use the protocol... $LJ::CAP{$_}->{checkfriends} = 0 foreach ( 0 .. 15 ); ( $res, $err ) = $do_request->("checkfriends"); $check_err->( 504, "Use 'checkforupdates' instead" ); ( $res, $err ) = $do_request->("checkforupdates"); $check_err->( 200, "Needs arguments" ); ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, flags => { noauth => 0 }, ); $check_err->( 101, "Have all arguments, but needs authorization" ); ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, ); $success->("Not authorized to use checkforupdates"); is_deeply( $res, { interval => 36000, new => 0 }, "Not authorized to use checkforupdates; no new entries, check back in an hour" ); # make sure everyone can use the protocol, and set interval to a known variable we can check against # (not using $LJ::T_HAS_ALL_CAPS = 1, because that makes everyone readonly) $LJ::CAP{$_}->{checkfriends} = 1 foreach ( 0 .. 15 ); $LJ::CAP{$_}->{checkfriends_interval} = 7 foreach ( 0 .. 15 ); ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, ); $success->("Checkforupdates. We don't watch anyone, but that's okay"); is( scalar %{ $u->watch_list }, 0, "Not watching anyone" ); is_deeply( $res, { interval => 7, new => 0, lastupdate => "0000-00-00 00:00:00", }, "Watching no one." ); # now we watch some people (who have no updates yet) my $userinfilter = temp_user(); $u->add_edge( $userinfilter, watch => { nonotify => 1 } ); $u->create_content_filter( name => "filter" ); my $filter = $u->content_filters( name => "filter" ); $filter->add_row( userid => $userinfilter->userid ); my $usernotinfilter = temp_user(); $u->add_edge( $usernotinfilter, watch => { nonotify => 1 } ); # and go through the protocol again ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, ); $success->("Checkforupdates. No one has updated."); is( scalar $u->watched_userids, 2 ); is_deeply( $res, { interval => 7, new => 0, lastupdate => "0000-00-00 00:00:00", }, "No new entries." ); # and then let's see what happens when they get updates $do_request->( "postevent", username => $userinfilter->user, event => "update", tz => "guess" ); sleep(1); # pause so we have different time stamps (for checking against) $do_request->( "postevent", username => $usernotinfilter->user, event => "update", tz => "guess" ); # use variables to make it easier to determine what I'm trying to check for # In some tests, I will deliberately *not* use the variables my $earlierupdate = $userinfilter->timeupdate; my $laterupdate = $usernotinfilter->timeupdate; ok( $earlierupdate < $laterupdate, "Timestamps need to be unequal for when we're testing stuff." ); # and go through the protocol again ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, ); $success->("Checkforupdates. Users have updated."); is_deeply( $res, { interval => 7, new => 0, lastupdate => LJ::mysql_time( $usernotinfilter->timeupdate ), }, "No new entries." ); # and we also check a subset (filter) ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, filter => $filter->name, ); $success->("Checkforupdates of a subset of watched users."); is_deeply( $res, { interval => 7, new => 0, lastupdate => LJ::mysql_time( $userinfilter->timeupdate ), }, "No new entries." ); # optional argument lastupdate ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, lastupdate => $earlierupdate ); $check_err->( 203, "lastupdate argument needs to be in mysql_time format." ); ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, lastupdate => LJ::mysql_time($earlierupdate), ); $success->("Checkforupdates since lastupdate. Have new updates"); is_deeply( $res, { interval => 7, new => 1, lastupdate => LJ::mysql_time($laterupdate), }, "Have new entries." ); ( $res, $err ) = $do_request->( "checkforupdates", username => $u->user, lastupdate => LJ::mysql_time($laterupdate), ); $success->("Checkforupdates since lastupdate. No new updates"); is_deeply( $res, { interval => 7, new => 0, lastupdate => LJ::mysql_time($laterupdate), }, "No new entries." ); } note("adding a comment to a journal"); { my $u = temp_user(); $u->update_self( { status => "A" } ); DW::Pay::add_paid_time( $u, "paid", 2 ); my $entry = $u->t_post_fake_entry; ( $res, $err ) = $do_request->( "addcomment", username => $u->user, ditemid => $entry->ditemid, subject => "subject", body => "comment body " . rand(), ); my $comment = LJ::Comment->new( $entry->journal, dtalkid => $res->{dtalkid} ); ok( $comment->poster->equals($u), "Check comment poster when posting to your own journal" ); ok( $comment->journal->equals($u), "Check comment journal when posting to your own journal" ); } note("adding a comment to a community"); { my $u = temp_user(); $u->update_self( { status => "A" } ); DW::Pay::add_paid_time( $u, "paid", 2 ); my $cu = temp_comm(); my $entry = $u->t_post_fake_comm_entry($cu); ( $res, $err ) = $do_request->( "addcomment", username => $u->user, journal => $cu->user, ditemid => $entry->ditemid, subject => "subject", body => "comment body " . rand(), ); my $comment = LJ::Comment->new( $entry->journal, dtalkid => $res->{dtalkid} ); ok( $comment->poster->equals($u), "Check comment poster when posting to a community" ); ok( $comment->journal->equals($cu), "Check comment journal when posting to a community" ); } note("adding a comment to another journal"); { my $u1 = temp_user(); $u1->update_self( { status => "A" } ); DW::Pay::add_paid_time( $u1, "paid", 2 ); my $u2 = temp_user(); my $entry = $u2->t_post_fake_entry; ( $res, $err ) = $do_request->( "addcomment", username => $u1->user, journal => $u2->user, ditemid => $entry->ditemid, subject => "subject", body => "comment body " . rand(), ); my $comment = LJ::Comment->new( $entry->journal, dtalkid => $res->{dtalkid} ); ok( $comment->poster->equals($u1), "Check comment poster when posting to another journal" ); ok( $comment->journal->equals($u2), "Check comment journal when posting to another journal" ); } note("getfriendspage"); { my $u = temp_user(); ( $res, $err ) = $do_request->( "getfriendspage", username => $u->user ); $check_err->( 504, "'getfriendspage' is deprecated." ); } note("getreadpage"); { my $u1 = temp_user(); my $u2 = temp_user(); $u1->add_edge( $u2, watch => { nonotify => 1 } ); my $e1 = $u2->t_post_fake_entry( body => "entry 1 " . rand(), subject => "#1", ); my $e2 = $u2->t_post_fake_entry( body => "entry 2 " . rand(), subject => "#2", ); my $e3 = $u2->t_post_fake_entry( body => "entry 3 " . rand(), subject => "#3", ); my @entries; # show everything ( $res, $err ) = $do_request->( "getreadpage", username => $u1->user, ); @entries = @{ $res->{entries} }; is( scalar @entries, 3, "3... 3 entries ah HA HA HA" ); is( $entries[0]->{subject_raw}, "#3" ); is( $entries[1]->{subject_raw}, "#2" ); is( $entries[2]->{subject_raw}, "#1" ); # limit to one item ( $res, $err ) = $do_request->( "getreadpage", username => $u1->user, itemshow => 1, ); @entries = @{ $res->{entries} }; is( scalar @entries, 1, "we asked for one entry" ); is( $entries[0]->{subject_raw}, "#3" ); # limit to one, skip one ( $res, $err ) = $do_request->( "getreadpage", username => $u1->user, itemshow => 1, skip => 1, ); @entries = @{ $res->{entries} }; is( scalar @entries, 1, "we asked for one entry (skip back one)" ); is( $entries[0]->{subject_raw}, "#2" ); }