From 6898c6d008a644152b2fd77365fd596cae712dee Mon Sep 17 00:00:00 2001 From: Irina Peshinskaya Date: Mon, 16 Apr 2018 13:39:16 +0200 Subject: [PATCH] TT#35607 Consider no_count query parameter and infinite next link Change-Id: I0e0b5407994b1ef24ef6060ce1679f2e5556f05f (cherry picked from commit ce3fde0c50bf513c4f85578a92a0494de091f9ce) --- lib/NGCP/Panel/Role/API.pm | 38 +++++++++++++++-- t/api-rest/api-subscriberregistrations.t | 1 + t/lib/Test/Collection.pm | 52 +++++++++++++++++++----- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/lib/NGCP/Panel/Role/API.pm b/lib/NGCP/Panel/Role/API.pm index 2e1ab29840..96a50bb1be 100644 --- a/lib/NGCP/Panel/Role/API.pm +++ b/lib/NGCP/Panel/Role/API.pm @@ -587,16 +587,45 @@ sub paginate_order_collection_array { return ($total_count, $items); } +sub dont_count_collection_total { + my ($self, $c) = @_; + my $no_count = defined $c->req->query_params->{no_count} ? $c->req->query_params->{no_count} : 0; + if ( !$no_count || ($no_count ne 'true' && $no_count ne '1' ) ) { + $no_count = 0; + } else { + $no_count = 1; + } + return $no_count; +} + +sub define_collection_infinite_pager { + my ($self, $c, $items_count, $item_rs, $rows_on_page, $no_count) = @_; + $no_count //= $self->dont_count_collection_total($c); + if (! defined $c->stash->{collection_infinite_pager_stop}) { + #$item_rs->pager->entries_on_this_page leads to the count query + my $entries_on_this_page = $items_count // $item_rs->count; + $c->stash->{collection_infinite_pager_stop} = (( $entries_on_this_page < $rows_on_page ) and $no_count ); + } +} + sub paginate_order_collection_rs { my ($self, $c, $item_rs, $params) = @_; my($page,$rows,$order_by,$direction) = @$params{qw/page rows order_by direction/}; my $result_class = $item_rs->result_class(); - my $total_count = int($item_rs->count); + + my $total_count; + my $no_count = $self->dont_count_collection_total($c); + if ( !$no_count ) { + $total_count = int($item_rs->count); + } + $item_rs = $item_rs->search(undef, { page => $page, rows => $rows, }); + $self->define_collection_infinite_pager($c, undef, $item_rs, $rows, $no_count); + if ($order_by && ((my $explicit = ($self->can('order_by_cols') && exists $self->order_by_cols()->{$order_by})) or $item_rs->result_source->has_column($order_by))) { my $col = ($explicit ? $self->order_by_cols()->{$order_by} : $item_rs->current_source_alias . '.' . $order_by); if (lc($direction) eq 'desc') { @@ -631,10 +660,13 @@ sub collection_nav_links { my @links = (Data::HAL::Link->new(relation => 'self', href => sprintf('/%s?page=%s&rows=%s%s', $path, $page, $rows, $rest_params))); - if(($total_count / $rows) > $page ) { + if ( (! defined $total_count + && ! $c->stash->{collection_infinite_pager_stop} ) + || ( defined $total_count && ($total_count / $rows) > $page ) ) { + push @links, Data::HAL::Link->new(relation => 'next', href => sprintf('/%s?page=%d&rows=%d%s', $path, $page + 1, $rows, $rest_params)); } - if($page > 1) { + if ($page > 1) { push @links, Data::HAL::Link->new(relation => 'prev', href => sprintf('/%s?page=%d&rows=%d%s', $path, $page - 1, $rows, $rest_params)); } return @links; diff --git a/t/api-rest/api-subscriberregistrations.t b/t/api-rest/api-subscriberregistrations.t index 6e18abdb47..7bcc38455f 100644 --- a/t/api-rest/api-subscriberregistrations.t +++ b/t/api-rest/api-subscriberregistrations.t @@ -11,6 +11,7 @@ use NGCP::Panel::Utils::DateTime; #init test_machine my $test_machine = Test::Collection->new( name => 'subscriberregistrations', + ALLOW_EMPTY_COLLECTION => 1, ); my $fake_data = Test::FakeData->new; diff --git a/t/lib/Test/Collection.pm b/t/lib/Test/Collection.pm index 2ee3e4bd82..ae3bd06555 100644 --- a/t/lib/Test/Collection.pm +++ b/t/lib/Test/Collection.pm @@ -191,6 +191,11 @@ has 'QUERY_PARAMS' =>( isa => 'Str', default => '', ); +has 'NO_COUNT' =>( + is => 'rw', + isa => 'Str', + default => '', +); has 'URI_CUSTOM_STORE' =>( is => 'rw', isa => 'Str', @@ -417,6 +422,12 @@ sub get_uri_collection{ $name //= $self->name; return $self->normalize_uri("/api/".$name.($name ? "/" : "").($self->QUERY_PARAMS ? "?".$self->QUERY_PARAMS : "")); } +sub get_uri_collection_paged{ + my($self,$name) = @_; + my $uri = $self->get_uri_collection($name); + return $uri.($uri !~/\?/ ? '?':'&').'page='.($self->PAGE // '1').'&rows='.($self->ROWS // '1').($self->NO_COUNT ? '&no_count=1' : ''); +} + sub get_uri_get{ my($self,$query_string, $name) = @_; $name //= $self->name; @@ -825,14 +836,20 @@ sub check_list_collection{ my($self, $check_embedded_cb) = @_; my $nexturi = $self->get_uri_collection."?page=1&rows=5"; my @href = (); + my $test_info_prefix = "$self->{name}: check_list_collection: "; do { #print "nexturi=$nexturi;\n"; my ($res,$list_collection) = $self->check_item_get($nexturi); my $selfuri = $self->normalize_uri($list_collection->{_links}->{self}->{href}); - is($selfuri, $nexturi, "$self->{name}: check _links.self.href of collection"); + my $sub_sort_params = sub {my $str = $_[0]; return (substr $str, 0, (index $str, '?') + 1) . join('&', sort split /&/, substr $str, ((index $str, '?') + 1))}; + $selfuri = $sub_sort_params->($selfuri); + $nexturi = $sub_sort_params->($nexturi); + is($selfuri, $nexturi, $test_info_prefix."check _links.self.href of collection"); my $colluri = URI->new($selfuri); - if(($list_collection->{total_count} && $list_collection->{total_count} > 0 ) || !$self->ALLOW_EMPTY_COLLECTION){ - ok($list_collection->{total_count} > 0, "$self->{name}: check 'total_count' of collection"); + if( + ((!$self->NO_COUNT) && $list_collection->{total_count} && is_int($list_collection->{total_count}) && $list_collection->{total_count} > 0 ) + || !$self->ALLOW_EMPTY_COLLECTION){ + ok($list_collection->{total_count} > 0, $test_info_prefix."check 'total_count' of collection"); } my %q = $colluri->query_form; @@ -845,10 +862,12 @@ sub check_list_collection{ } else { ok(exists $list_collection->{_links}->{prev}->{href}, "$self->{name}: check existence of 'prev'"); } - if(($rows != 0) && ($list_collection->{total_count} / $rows) <= $page) { - ok(!exists $list_collection->{_links}->{next}->{href}, "$self->{name}: check absence of 'next' on last page"); - } else { - ok(exists $list_collection->{_links}->{next}->{href}, "$self->{name}: check existence of 'next'"); + if (!$self->NO_COUNT) { + if(($rows != 0) && ($list_collection->{total_count} / $rows) <= $page) { + ok(!exists $list_collection->{_links}->{next}->{href}, $test_info_prefix."check absence of 'next' on last page"); + } else { + ok(exists $list_collection->{_links}->{next}->{href}, $test_info_prefix."check existence of 'next'"); + } } if($list_collection->{_links}->{next}->{href}) { @@ -858,9 +877,11 @@ sub check_list_collection{ } my $hal_name = $self->get_hal_name; - if(($list_collection->{total_count} && $list_collection->{total_count} > 0 ) || !$self->ALLOW_EMPTY_COLLECTION){ - ok(((ref $list_collection->{_links}->{$hal_name} eq "ARRAY" ) || - (ref $list_collection->{_links}->{$hal_name} eq "HASH" ) ), "$self->{name}: check if 'ngcp:".$self->name."' is array/hash-ref"); + if(($list_collection->{total_count} && is_int($list_collection->{total_count}) && $list_collection->{total_count} > 0 ) || !$self->ALLOW_EMPTY_COLLECTION){ + if (! ok(((ref $list_collection->{_links}->{$hal_name} eq "ARRAY" ) || + (ref $list_collection->{_links}->{$hal_name} eq "HASH" ) ), $test_info_prefix."check if 'ngcp:".$self->name."' is array/hash-ref")) { + diag($list_collection->{_links}->{$hal_name}); + } } @@ -1078,6 +1099,9 @@ sub check_bundle{ if($self->methods->{collection}->{allowed}->{GET}){ $listed = $self->check_list_collection(); $self->check_created_listed($listed); + $self->NO_COUNT('1'); + $self->check_list_collection(); + $self->NO_COUNT(''); } # test model item if(@$listed && !$self->NO_ITEM_MODULE){ @@ -1438,5 +1462,11 @@ sub clear_cache{ `$cmd`; } } - +sub is_int { + my $val = shift; + if($val =~ /^[+-]?[0-9]+$/) { + return 1; + } + return; +} 1;