| Lines 17-23
          
      
      
        Link Here | 
        
          | 17 |  | 17 |  | 
        
          | 18 | use Modern::Perl; | 18 | use Modern::Perl; | 
        
          | 19 |  | 19 |  | 
          
            
              | 20 | use Test::More tests => 1; | 20 | use Test::More tests => 5; | 
        
          | 21 | use Test::Mojo; | 21 | use Test::Mojo; | 
        
          | 22 |  | 22 |  | 
        
          | 23 | use JSON qw(encode_json); | 23 | use JSON qw(encode_json); | 
  
    | Lines 51-123
          subtest 'list_public() tests' => sub {
      
      
        Link Here | 
        
          | 51 |     $patron_2->set_password( { password => $password, skip_validation => 1 } ); | 51 |     $patron_2->set_password( { password => $password, skip_validation => 1 } ); | 
        
          | 52 |     my $patron_2_userid = $patron_2->userid; | 52 |     my $patron_2_userid = $patron_2->userid; | 
        
          | 53 |  | 53 |  | 
          
            
              | 54 |     my $list_1 = | 54 |     my $list_1 = $builder->build_object( | 
            
              | 55 |         $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_1->id, public => 1 } } ); |  |  | 
            
              | 56 |     my $list_2 = | 
            
              | 57 |         $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_1->id, public => 0 } } ); | 
            
              | 58 |     my $list_3 = | 
            
              | 59 |         $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_2->id, public => 1 } } ); | 
            
              | 60 |     my $list_4 = | 
            
              | 61 |         $builder->build_object( { class => 'Koha::Virtualshelves', value => { owner => $patron_2->id, public => 0 } } ); | 
            
              | 62 |  | 
            
              | 63 |     my $q = encode_json( | 
        
          | 64 |         { | 55 |         { | 
          
            
              | 65 |             list_id => { | 56 |             class => 'Koha::Virtualshelves', | 
            
              | 66 |                 -in => [ | 57 |             value => { owner => $patron_1->id, public => 1 } | 
            
              | 67 |                     $list_1->id, | 58 |         } | 
            
              | 68 |                     $list_2->id, | 59 |     ); | 
            
              | 69 |                     $list_3->id, | 60 |     my $list_2 = $builder->build_object( | 
            
              | 70 |                     $list_4->id, | 61 |         { | 
            
              | 71 |                 ] | 62 |             class => 'Koha::Virtualshelves', | 
            
              | 72 |             } | 63 |             value => { owner => $patron_1->id, public => 0 } | 
            
              |  |  | 64 |         } | 
            
              | 65 |     ); | 
            
              | 66 |     my $list_3 = $builder->build_object( | 
            
              | 67 |         { | 
            
              | 68 |             class => 'Koha::Virtualshelves', | 
            
              | 69 |             value => { owner => $patron_2->id, public => 1 } | 
            
              | 70 |         } | 
            
              | 71 |     ); | 
            
              | 72 |     my $list_4 = $builder->build_object( | 
            
              | 73 |         { | 
            
              | 74 |             class => 'Koha::Virtualshelves', | 
            
              | 75 |             value => { owner => $patron_2->id, public => 0 } | 
        
          | 73 |         } | 76 |         } | 
        
          | 74 |     ); | 77 |     ); | 
        
          | 75 |  | 78 |  | 
            
              |  |  | 79 |     my $q = encode_json( { list_id => { -in => [ $list_1->id, $list_2->id, $list_3->id, $list_4->id, ] } } ); | 
            
              | 80 |  | 
        
          | 76 |     # anonymous | 81 |     # anonymous | 
          
            
              | 77 |     $t->get_ok("/api/v1/public/lists?q=$q")->status_is( 200, "Anonymous users can only fetch public lists" ) | 82 |     $t->get_ok("/api/v1/public/lists?q=$q")->status_is( 200, "Anonymous users can only fetch public lists" )->json_is( | 
            
              | 78 |         ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] ); | 83 |         [ | 
            
              |  |  | 84 |             $list_1->to_api( { public => 1 } ), | 
            
              | 85 |             $list_3->to_api( { public => 1 } ) | 
            
              | 86 |         ] | 
            
              | 87 |     ); | 
        
          | 79 |  | 88 |  | 
        
          | 80 |     $t->get_ok("/api/v1/public/lists?q=$q&only_public=1") | 89 |     $t->get_ok("/api/v1/public/lists?q=$q&only_public=1") | 
          
            
              | 81 |         ->status_is( 200, "Anonymous users can only fetch public lists" ) | 90 |         ->status_is( 200, "Anonymous users can only fetch public lists" )->json_is( | 
            
              | 82 |         ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] ); | 91 |         [ | 
            
              |  |  | 92 |             $list_1->to_api( { public => 1 } ), | 
            
              | 93 |             $list_3->to_api( { public => 1 } ) | 
            
              | 94 |         ] | 
            
              | 95 |         ); | 
        
          | 83 |  | 96 |  | 
          
            
              | 84 |     $t->get_ok("/api/v1/public/lists?q=$q&only_mine=1") | 97 |     $t->get_ok("/api/v1/public/lists?q=$q&only_mine=1")->status_is( | 
            
              | 85 |         ->status_is( 400, "Passing only_mine on an anonymous session generates a 400 code" ) | 98 |         400, | 
            
              | 86 |         ->json_is( '/error_code' => q{only_mine_forbidden} ); | 99 |         "Passing only_mine on an anonymous session generates a 400 code" | 
            
              |  |  | 100 |     )->json_is( '/error_code' => q{only_mine_forbidden} ); | 
        
          | 87 |  | 101 |  | 
          
            
              | 88 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_mine=1") | 102 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_mine=1")->status_is( | 
            
              | 89 |         ->status_is( 200, "Passing only_mine with a logged in user makes it return only their lists" ) | 103 |         200, | 
            
              | 90 |         ->json_is( [ $list_1->to_api( { public => 1 } ), $list_2->to_api( { public => 1 } ) ] ); | 104 |         "Passing only_mine with a logged in user makes it return only their lists" | 
            
              |  |  | 105 |     )->json_is( | 
            
              | 106 |         [ | 
            
              | 107 |             $list_1->to_api( { public => 1 } ), | 
            
              | 108 |             $list_2->to_api( { public => 1 } ) | 
            
              | 109 |         ] | 
            
              | 110 |     ); | 
        
          | 91 |  | 111 |  | 
          
            
              | 92 |     $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_mine=1") | 112 |     $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_mine=1")->status_is( | 
            
              | 93 |         ->status_is( 200, "Passing only_mine with a logged in user makes it return only their lists" ) | 113 |         200, | 
            
              | 94 |         ->json_is( [ $list_3->to_api( { public => 1 } ), $list_4->to_api( { public => 1 } ) ] ); | 114 |         "Passing only_mine with a logged in user makes it return only their lists" | 
            
              |  |  | 115 |     )->json_is( | 
            
              | 116 |         [ | 
            
              | 117 |             $list_3->to_api( { public => 1 } ), | 
            
              | 118 |             $list_4->to_api( { public => 1 } ) | 
            
              | 119 |         ] | 
            
              | 120 |     ); | 
        
          | 95 |  | 121 |  | 
        
          | 96 |     # only public | 122 |     # only public | 
          
            
              | 97 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1") | 123 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1")->status_is( | 
            
              | 98 |         ->status_is( 200, "Passing only_public with a logged in user makes it return only public lists" ) | 124 |         200, | 
            
              | 99 |         ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] ); | 125 |         "Passing only_public with a logged in user makes it return only public lists" | 
            
              | 100 |  | 126 |     )->json_is( | 
            
              | 101 |     $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_public=1") | 127 |         [ | 
            
              | 102 |         ->status_is( 200, "Passing only_public with a logged in user makes it return only public lists" ) | 128 |             $list_1->to_api( { public => 1 } ), | 
            
              | 103 |         ->json_is( [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] ); | 129 |             $list_3->to_api( { public => 1 } ) | 
            
              | 104 |  | 130 |         ] | 
            
              | 105 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q") | 131 |     ); | 
            
              | 106 |         ->status_is( 200, "Not filtering with only_mine or only_public makes it return all accessible lists" ) | 132 |  | 
            
              | 107 |         ->json_is( | 133 |     $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q&only_public=1")->status_is( | 
            
              | 108 |         [ $list_1->to_api( { public => 1 } ), $list_2->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ) ] | 134 |         200, | 
            
              |  |  | 135 |         "Passing only_public with a logged in user makes it return only public lists" | 
            
              | 136 |     )->json_is( | 
            
              | 137 |         [ | 
            
              | 138 |             $list_1->to_api( { public => 1 } ), | 
            
              | 139 |             $list_3->to_api( { public => 1 } ) | 
            
              | 140 |         ] | 
            
              | 141 |     ); | 
            
              | 142 |  | 
            
              | 143 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q")->status_is( | 
            
              | 144 |         200, | 
            
              | 145 |         "Not filtering with only_mine or only_public makes it return all accessible lists" | 
            
              | 146 |     )->json_is( | 
            
              | 147 |         [ | 
            
              | 148 |             $list_1->to_api( { public => 1 } ), | 
            
              | 149 |             $list_2->to_api( { public => 1 } ), | 
            
              | 150 |             $list_3->to_api( { public => 1 } ) | 
            
              | 151 |         ] | 
            
              | 152 |     ); | 
            
              | 153 |  | 
            
              | 154 |     $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q")->status_is( | 
            
              | 155 |         200, | 
            
              | 156 |         "Not filtering with only_mine or only_public makes it return all accessible lists" | 
            
              | 157 |     )->json_is( | 
            
              | 158 |         [ | 
            
              | 159 |             $list_1->to_api( { public => 1 } ), | 
            
              | 160 |             $list_3->to_api( { public => 1 } ), | 
            
              | 161 |             $list_4->to_api( { public => 1 } ) | 
            
              | 162 |         ] | 
            
              | 163 |     ); | 
            
              | 164 |  | 
            
              | 165 |     # conflicting params | 
            
              | 166 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1&only_mine=1")->status_is( | 
            
              | 167 |         200, | 
            
              | 168 |         "Passing only_public with a logged in user makes it return only public lists" | 
            
              | 169 |     )->json_is( [ $list_1->to_api( { public => 1 } ) ] ); | 
            
              | 170 |  | 
            
              | 171 |     $schema->storage->txn_rollback; | 
            
              | 172 | }; | 
            
              | 173 |  | 
            
              | 174 | subtest 'public_get() tests' => sub { | 
            
              | 175 |     plan tests => 12; | 
            
              | 176 |  | 
            
              | 177 |     $schema->storage->txn_begin; | 
            
              | 178 |  | 
            
              | 179 |     my $password = 'thePassword123'; | 
            
              | 180 |     my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 181 |     my $patron_2 = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 182 |  | 
            
              | 183 |     $patron_1->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 184 |     $patron_2->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 185 |  | 
            
              | 186 |     my $patron_1_userid = $patron_1->userid; | 
            
              | 187 |     my $patron_2_userid = $patron_2->userid; | 
            
              | 188 |  | 
            
              | 189 |     # Create test lists | 
            
              | 190 |     my $public_list = $builder->build_object( | 
            
              | 191 |         { | 
            
              | 192 |             class => 'Koha::Virtualshelves', | 
            
              | 193 |             value => { | 
            
              | 194 |                 owner                   => $patron_1->id, | 
            
              | 195 |                 public                  => 1, | 
            
              | 196 |                 allow_change_from_owner => 1 | 
            
              | 197 |             } | 
            
              | 198 |         } | 
            
              | 199 |     ); | 
            
              | 200 |  | 
            
              | 201 |     my $private_list = $builder->build_object( | 
            
              | 202 |         { | 
            
              | 203 |             class => 'Koha::Virtualshelves', | 
            
              | 204 |             value => { | 
            
              | 205 |                 owner                   => $patron_1->id, | 
            
              | 206 |                 public                  => 0, | 
            
              | 207 |                 allow_change_from_owner => 0 | 
            
              | 208 |             } | 
            
              | 209 |         } | 
            
              | 210 |     ); | 
            
              | 211 |  | 
            
              | 212 |     # Test anonymous access to public list | 
            
              | 213 |     $t->get_ok( "/api/v1/public/lists/" . $public_list->id )->status_is(200)->json_is( $public_list->to_api ); | 
            
              | 214 |  | 
            
              | 215 |     # Test anonymous access to private list | 
            
              | 216 |     $t->get_ok( "/api/v1/public/lists/" . $private_list->id ) | 
            
              | 217 |         ->status_is( 403, 'Anonymous user cannot access private list' ); | 
            
              | 218 |  | 
            
              | 219 |     # Test authenticated access - owner can see their private list | 
            
              | 220 |     $t->get_ok( "//$patron_1_userid:$password@/api/v1/public/lists/" . $private_list->id )->status_is(200) | 
            
              | 221 |         ->json_is( $private_list->to_api ); | 
            
              | 222 |  | 
            
              | 223 |     # Test non-owner access to private list | 
            
              | 224 |     $t->get_ok( "//$patron_2_userid:$password@/api/v1/public/lists/" . $private_list->id ) | 
            
              | 225 |         ->status_is( 403, 'Non-owner cannot access private list' ); | 
            
              | 226 |  | 
            
              | 227 |     # Test non-existent list | 
            
              | 228 |     $t->get_ok("/api/v1/public/lists/99999999")->status_is( 404, "List not found" ); | 
            
              | 229 |  | 
            
              | 230 |     $schema->storage->txn_rollback; | 
            
              | 231 | }; | 
            
              | 232 |  | 
            
              | 233 | subtest 'public_add() tests' => sub { | 
            
              | 234 |     plan tests => 9;    # Reduced test count since we're removing one assertion | 
            
              | 235 |  | 
            
              | 236 |     $schema->storage->txn_begin; | 
            
              | 237 |  | 
            
              | 238 |     my $password       = 'thePassword123'; | 
            
              | 239 |     my $patron         = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 240 |     my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 241 |     $patron->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 242 |     my $patron_userid = $patron->userid; | 
            
              | 243 |  | 
            
              | 244 |     my $list_data = { | 
            
              | 245 |         name                     => "Test List", | 
            
              | 246 |         public                   => 1, | 
            
              | 247 |         allow_change_from_owner  => 1, | 
            
              | 248 |         allow_change_from_others => 0, | 
            
              | 249 |         default_sort_field       => 'title' | 
            
              | 250 |     }; | 
            
              | 251 |  | 
            
              | 252 |     # Test anonymous attempt | 
            
              | 253 |     $t->post_ok( "/api/v1/public/lists" => json => $list_data )->status_is( 401, 'Anonymous user cannot create list' ); | 
            
              | 254 |  | 
            
              | 255 |     # Test authenticated user can create list | 
            
              | 256 |     $t->post_ok( "//$patron_userid:$password@/api/v1/public/lists" => json => $list_data )->status_is(201) | 
            
              | 257 |         ->json_has( '/list_id', 'List ID is present in response' ) | 
            
              | 258 |         ->json_has( '/name',    'List name is present in response' )->json_is( | 
            
              | 259 |         '/owner_id' => $patron->id, | 
            
              | 260 |         'List created with logged in user as owner' | 
        
          | 109 |         ); | 261 |         ); | 
        
          | 110 |  | 262 |  | 
          
            
              | 111 |     $t->get_ok("//$patron_2_userid:$password@/api/v1/public/lists?q=$q") | 263 |     # Test attempt to specify owner_id | 
            
              | 112 |         ->status_is( 200, "Not filtering with only_mine or only_public makes it return all accessible lists" ) | 264 |     my $list_with_owner = { | 
            
              | 113 |         ->json_is( | 265 |         name                     => "Test List", | 
            
              | 114 |         [ $list_1->to_api( { public => 1 } ), $list_3->to_api( { public => 1 } ), $list_4->to_api( { public => 1 } ) ] | 266 |         owner_id                 => $another_patron->id,    # Should be rejected | 
            
              |  |  | 267 |         public                   => 1, | 
            
              | 268 |         allow_change_from_owner  => 1, | 
            
              | 269 |         allow_change_from_others => 0, | 
            
              | 270 |         default_sort_field       => 'title' | 
            
              | 271 |     }; | 
            
              | 272 |  | 
            
              | 273 |     $t->post_ok( "//$patron_userid:$password@/api/v1/public/lists" => json => $list_with_owner )->status_is(400); | 
            
              | 274 |  | 
            
              | 275 |     $schema->storage->txn_rollback; | 
            
              | 276 | }; | 
            
              | 277 |  | 
            
              | 278 | subtest 'public_update() tests' => sub { | 
            
              | 279 |     plan tests => 15; | 
            
              | 280 |  | 
            
              | 281 |     $schema->storage->txn_begin; | 
            
              | 282 |  | 
            
              | 283 |     my $password       = 'thePassword123'; | 
            
              | 284 |     my $patron         = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 285 |     my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 286 |  | 
            
              | 287 |     $patron->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 288 |     $another_patron->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 289 |  | 
            
              | 290 |     my $patron_userid         = $patron->userid; | 
            
              | 291 |     my $another_patron_userid = $another_patron->userid; | 
            
              | 292 |  | 
            
              | 293 |     # Create a list that can be modified | 
            
              | 294 |     my $modifiable_list = $builder->build_object( | 
            
              | 295 |         { | 
            
              | 296 |             class => 'Koha::Virtualshelves', | 
            
              | 297 |             value => { | 
            
              | 298 |                 owner                   => $patron->id, | 
            
              | 299 |                 public                  => 1, | 
            
              | 300 |                 allow_change_from_owner => 1 | 
            
              | 301 |             } | 
            
              | 302 |         } | 
            
              | 303 |     ); | 
            
              | 304 |  | 
            
              | 305 |     # Create a list that cannot be modified | 
            
              | 306 |     my $unmodifiable_list = $builder->build_object( | 
            
              | 307 |         { | 
            
              | 308 |             class => 'Koha::Virtualshelves', | 
            
              | 309 |             value => { | 
            
              | 310 |                 owner                   => $patron->id, | 
            
              | 311 |                 public                  => 1, | 
            
              | 312 |                 allow_change_from_owner => 0 | 
            
              | 313 |             } | 
            
              | 314 |         } | 
            
              | 315 |     ); | 
            
              | 316 |  | 
            
              | 317 |     my $update_data = { | 
            
              | 318 |         name                     => "Updated List Name", | 
            
              | 319 |         public                   => 0, | 
            
              | 320 |         allow_change_from_owner  => 1, | 
            
              | 321 |         allow_change_from_others => 0, | 
            
              | 322 |         default_sort_field       => 'title' | 
            
              | 323 |     }; | 
            
              | 324 |  | 
            
              | 325 |     # Test anonymous attempt | 
            
              | 326 |     $t->put_ok( "/api/v1/public/lists/" . $modifiable_list->id => json => $update_data ) | 
            
              | 327 |         ->status_is( 401, 'Anonymous user cannot update list' ); | 
            
              | 328 |  | 
            
              | 329 |     # Test non-owner update attempt | 
            
              | 330 |     $t->put_ok( | 
            
              | 331 |         "//$another_patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id => json => $update_data ) | 
            
              | 332 |         ->status_is( 403, 'Non-owner cannot update list' ); | 
            
              | 333 |  | 
            
              | 334 |     # Test owner update success | 
            
              | 335 |     $t->put_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id => json => $update_data ) | 
            
              | 336 |         ->status_is(200)->json_is( '/name' => 'Updated List Name', 'List name updated' ) | 
            
              | 337 |         ->json_is( '/public' => 0, 'List privacy updated' ); | 
            
              | 338 |  | 
            
              | 339 |     # Test update of non-existent list | 
            
              | 340 |     $t->put_ok( "//$patron_userid:$password@/api/v1/public/lists/99999999" => json => $update_data ) | 
            
              | 341 |         ->status_is( 404, "List not found" ); | 
            
              | 342 |  | 
            
              | 343 |     # Test update of unmodifiable list | 
            
              | 344 |     $t->put_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $unmodifiable_list->id => json => $update_data ) | 
            
              | 345 |         ->status_is( | 
            
              | 346 |         403, | 
            
              | 347 |         "Cannot update list when allow_change_from_owner is false" | 
            
              | 348 |     )->json_is( '/error_code' => 'forbidden', 'Correct error code returned' ); | 
            
              | 349 |  | 
            
              | 350 |     # Create librarian with necessary permissions | 
            
              | 351 |     my $librarian = $builder->build_object( | 
            
              | 352 |         { | 
            
              | 353 |             class => 'Koha::Patrons', | 
            
              | 354 |             value => { flags => 2**13 } | 
            
              | 355 |         } | 
            
              | 356 |     ); | 
            
              | 357 |     $librarian->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 358 |     my $librarian_userid = $librarian->userid; | 
            
              | 359 |  | 
            
              | 360 |     # Test librarian using public endpoint | 
            
              | 361 |     $t->put_ok( "//$librarian_userid:$password@/api/v1/public/lists/" . $modifiable_list->id => json => $update_data ) | 
            
              | 362 |         ->status_is( | 
            
              | 363 |         403, | 
            
              | 364 |         'Librarian must use admin endpoint to modify others lists' | 
        
          | 115 |         ); | 365 |         ); | 
        
          | 116 |  | 366 |  | 
          
            
              | 117 |     # conflicting params | 367 |     $schema->storage->txn_rollback; | 
            
              | 118 |     $t->get_ok("//$patron_1_userid:$password@/api/v1/public/lists?q=$q&only_public=1&only_mine=1") | 368 | }; | 
            
              | 119 |         ->status_is( 200, "Passing only_public with a logged in user makes it return only public lists" ) | 369 |  | 
            
              | 120 |         ->json_is( [ $list_1->to_api( { public => 1 } ) ] ); | 370 | subtest 'public_delete() tests' => sub { | 
            
              |  |  | 371 |     plan tests => 12; | 
            
              | 372 |  | 
            
              | 373 |     $schema->storage->txn_begin; | 
            
              | 374 |  | 
            
              | 375 |     my $password       = 'thePassword123'; | 
            
              | 376 |     my $patron         = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 377 |     my $another_patron = $builder->build_object( { class => 'Koha::Patrons' } ); | 
            
              | 378 |  | 
            
              | 379 |     $patron->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 380 |     $another_patron->set_password( { password => $password, skip_validation => 1 } ); | 
            
              | 381 |  | 
            
              | 382 |     my $patron_userid         = $patron->userid; | 
            
              | 383 |     my $another_patron_userid = $another_patron->userid; | 
            
              | 384 |  | 
            
              | 385 |     # Create test lists for different scenarios | 
            
              | 386 |     my $modifiable_list = $builder->build_object( | 
            
              | 387 |         { | 
            
              | 388 |             class => 'Koha::Virtualshelves', | 
            
              | 389 |             value => { | 
            
              | 390 |                 owner                   => $patron->id, | 
            
              | 391 |                 public                  => 1, | 
            
              | 392 |                 allow_change_from_owner => 1 | 
            
              | 393 |             } | 
            
              | 394 |         } | 
            
              | 395 |     ); | 
            
              | 396 |  | 
            
              | 397 |     my $other_patron_list = $builder->build_object( | 
            
              | 398 |         { | 
            
              | 399 |             class => 'Koha::Virtualshelves', | 
            
              | 400 |             value => { | 
            
              | 401 |                 owner                   => $another_patron->id, | 
            
              | 402 |                 public                  => 1, | 
            
              | 403 |                 allow_change_from_owner => 1 | 
            
              | 404 |             } | 
            
              | 405 |         } | 
            
              | 406 |     ); | 
            
              | 407 |  | 
            
              | 408 |     my $unmodifiable_list = $builder->build_object( | 
            
              | 409 |         { | 
            
              | 410 |             class => 'Koha::Virtualshelves', | 
            
              | 411 |             value => { | 
            
              | 412 |                 owner                   => $patron->id, | 
            
              | 413 |                 public                  => 1, | 
            
              | 414 |                 allow_change_from_owner => 0 | 
            
              | 415 |             } | 
            
              | 416 |         } | 
            
              | 417 |     ); | 
            
              | 418 |  | 
            
              | 419 |     # Test anonymous attempt | 
            
              | 420 |     $t->delete_ok( "/api/v1/public/lists/" . $modifiable_list->id ) | 
            
              | 421 |         ->status_is( 401, 'Anonymous user cannot delete list' ); | 
            
              | 422 |  | 
            
              | 423 |     # Test non-owner delete attempt | 
            
              | 424 |     $t->delete_ok( "//$another_patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id ) | 
            
              | 425 |         ->status_is( 403, 'Non-owner cannot delete list' ); | 
            
              | 426 |  | 
            
              | 427 |     # Test attempt to delete another patron's list | 
            
              | 428 |     $t->delete_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $other_patron_list->id ) | 
            
              | 429 |         ->status_is( 403, "Cannot delete another patron's list" ); | 
            
              | 430 |  | 
            
              | 431 |     # Test delete of unmodifiable list | 
            
              | 432 |     $t->delete_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $unmodifiable_list->id )->status_is( | 
            
              | 433 |         403, | 
            
              | 434 |         "Cannot delete list when allow_change_from_owner is false" | 
            
              | 435 |     ); | 
            
              | 436 |  | 
            
              | 437 |     # Test delete of non-existent list | 
            
              | 438 |     $t->delete_ok("//$patron_userid:$password@/api/v1/public/lists/99999999")->status_is( 404, "List not found" ); | 
            
              | 439 |  | 
            
              | 440 |     # Test successful delete by owner | 
            
              | 441 |     $t->delete_ok( "//$patron_userid:$password@/api/v1/public/lists/" . $modifiable_list->id ) | 
            
              | 442 |         ->status_is( 204, 'List deleted successfully' ); | 
        
          | 121 |  | 443 |  | 
        
          | 122 |     $schema->storage->txn_rollback; | 444 |     $schema->storage->txn_rollback; | 
        
          | 123 | }; | 445 | }; | 
          
            
              | 124 | -  | 446 |  | 
            
              |  |  | 447 | 1; |