Skip to content

Commit 11c6a73

Browse files
authored
Merge pull request #876 from metacpan/ssoriche/spec_cover
Create Model, Controller and spec for Cover
2 parents 2e7998e + e515f05 commit 11c6a73

File tree

12 files changed

+197
-67
lines changed

12 files changed

+197
-67
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package MetaCPAN::API::Controller::Cover;
2+
3+
use Mojo::Base 'Mojolicious::Controller';
4+
5+
sub lookup {
6+
my $c = shift;
7+
return unless $c->openapi->valid_input;
8+
my $args = $c->validation->output;
9+
10+
my $results = $c->model->cover->find_release_coverage( $args->{name} );
11+
return $c->render( openapi => $results ) if $results;
12+
$c->rendered(404);
13+
}
14+
15+
1;
16+

lib/MetaCPAN/API/Model/Cover.pm

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package MetaCPAN::API::Model::Cover;
2+
3+
use MetaCPAN::Moose;
4+
5+
with 'MetaCPAN::API::Model::Role::ES';
6+
7+
sub find_release_coverage {
8+
my ( $self, $release ) = @_;
9+
10+
my $query = +{ term => { release => $release } };
11+
12+
my $res = $self->_run_query(
13+
index => 'cover',
14+
type => 'cover',
15+
body => {
16+
query => $query,
17+
size => 999,
18+
}
19+
);
20+
$res->{hits}{total} or return {};
21+
22+
return +{
23+
%{ $res->{hits}{hits}[0]{_source} },
24+
url => "http://cpancover.com/latest/$release/index.html",
25+
};
26+
}
27+
28+
__PACKAGE__->meta->make_immutable;
29+
30+
1;
31+

lib/MetaCPAN/API/Plugin/Model.pm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use MetaCPAN::Model::Search ();
1010
# New models
1111
use MetaCPAN::API::Model::User ();
1212
use MetaCPAN::API::Model::Download ();
13+
use MetaCPAN::API::Model::Cover ();
1314

1415
has app => sub { Carp::croak 'app is required' }, weak => 1;
1516

@@ -31,6 +32,11 @@ has user => sub {
3132
return MetaCPAN::API::Model::User->new( es => $self->app->es );
3233
};
3334

35+
has cover => sub {
36+
my $self = shift;
37+
return MetaCPAN::API::Model::Cover->new( es => $self->app->es );
38+
};
39+
3440
sub register {
3541
my ( $plugin, $app, $conf ) = @_;
3642
$plugin->app($app);
@@ -39,6 +45,7 @@ sub register {
3945
$app->helper( 'model.download' => sub { $plugin->download } );
4046
$app->helper( 'model.search' => sub { $plugin->search } );
4147
$app->helper( 'model.user' => sub { $plugin->user } );
48+
$app->helper( 'model.cover' => sub { $plugin->cover } );
4249
}
4350

4451
1;

lib/MetaCPAN/Script/Cover.pm

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use namespace::autoclean;
55

66
use Cpanel::JSON::XS qw( decode_json );
77
use Log::Contextual qw( :log :dlog );
8-
use MetaCPAN::Types qw( Bool Uri);
8+
use MetaCPAN::Types qw( Bool Str Uri);
9+
use Path::Class qw( file );
910

1011
with 'MetaCPAN::Role::Script', 'MooseX::Getopt';
1112

@@ -30,6 +31,14 @@ has test => (
3031
documentation => 'Test mode (pulls smaller development data set)',
3132
);
3233

34+
has json_file => (
35+
is => 'ro',
36+
isa => Str,
37+
default => 0,
38+
documentation =>
39+
'Path to JSON file to be read instead of URL (for testing)',
40+
);
41+
3342
my %valid_keys
3443
= map { $_ => 1 } qw< branch condition statement subroutine total >;
3544

@@ -96,6 +105,11 @@ sub index_cover_data {
96105
sub retrieve_cover_data {
97106
my $self = shift;
98107

108+
if ( $self->json_file ) {
109+
my $file = file( $self->json_file );
110+
return decode_json( $file->slurp );
111+
}
112+
99113
my $url = $self->test ? $self->cover_dev_url : $self->cover_url;
100114

101115
log_info { 'Fetching data from ', $url };
@@ -129,4 +143,3 @@ Retrieves the CPAN cover data from its source and
129143
updates our ES information.
130144
131145
=cut
132-

root/static/definitions/common.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
3+
ErrorModel:
4+
type: "object"
5+
required:
6+
- "code"
7+
- "message"
8+
properties:
9+
code:
10+
type: "integer"
11+
format: "int32"
12+
message:
13+
type: "string"

root/static/requests/cover.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
3+
cover:
4+
get:
5+
tags:
6+
- Coverage
7+
operationId: cover
8+
x-mojo-to: Cover#lookup
9+
summary: Get coverage details about a release
10+
parameters:
11+
- name: name
12+
in: path
13+
description: |
14+
The name of the Release
15+
type: string
16+
required: true
17+
# tell Mojolicious to use relaxed placeholders when
18+
# parsing this parameter (dots are allowed)
19+
x-mojo-placeholder: "#"
20+
responses:
21+
200:
22+
description: Release response
23+
schema:
24+
type: object
25+
properties:
26+
name:
27+
type: string
28+
default:
29+
description: "unexpected error"
30+
schema:
31+
$ref: "../definitions/common.yml#/ErrorModel"

root/static/v1.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ paths:
2222
$ref: "requests/search.yml#/search_web"
2323
/search/first:
2424
$ref: "requests/search.yml#/search_first"
25+
/cover/{name}:
26+
$ref: "requests/cover.yml#/cover"

t/00_setup.t

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ $server->prepare_user_test_data;
105105
$server->index_cpantesters;
106106
$server->index_mirrors;
107107
$server->index_favorite;
108+
$server->index_cover;
108109

109110
ok(
110111
MetaCPAN::Script::Tickets->new_with_options(

t/api/controller/cover.t

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use Mojo::Base -strict;
2+
use lib 't/lib';
3+
4+
use Test::More;
5+
use Test::Mojo;
6+
use Mojo::JSON qw(true false);
7+
8+
use MetaCPAN::Model::Search ();
9+
use MetaCPAN::TestServer ();
10+
my $server = MetaCPAN::TestServer->new;
11+
12+
my $t = Test::Mojo->new(
13+
'MetaCPAN::API' => {
14+
es => $server->es_client,
15+
secret => 'just a test',
16+
}
17+
);
18+
19+
my %expect = (
20+
'MetaFile-Both-1.1' => {
21+
criteria => {
22+
branch => '12.50',
23+
condition => '0.00',
24+
statement => '63.64',
25+
subroutine => '71.43',
26+
total => '46.51',
27+
},
28+
distribution => 'MetaFile-Both',
29+
release => 'MetaFile-Both-1.1',
30+
url => 'http://cpancover.com/latest/MetaFile-Both-1.1/index.html',
31+
version => '1.1',
32+
},
33+
'Pod-With-Generator-1' => {
34+
criteria => {
35+
branch => '78.95',
36+
condition => '46.67',
37+
statement => '95.06',
38+
subroutine => '100.00',
39+
total => '86.58',
40+
},
41+
distribution => 'Pod-With-Generator',
42+
release => 'Pod-With-Generator-1',
43+
url => 'http://cpancover.com/latest/Pod-With-Generator-1/index.html',
44+
version => '1',
45+
},
46+
);
47+
48+
for my $release ( keys %expect ) {
49+
my $expected = $expect{$release};
50+
subtest "Check $release" => sub {
51+
52+
$t->get_ok("/v1/cover/$release")->status_is(200)->json_is($expected)
53+
->or( sub { diag $t->tx->res->dom } );
54+
55+
};
56+
}
57+
done_testing;

t/lib/MetaCPAN/TestServer.pm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use MetaCPAN::Moose;
44

55
use MetaCPAN::DarkPAN ();
66
use MetaCPAN::Script::Author ();
7+
use MetaCPAN::Script::Cover ();
78
use MetaCPAN::Script::CPANTestersAPI ();
89
use MetaCPAN::Script::Favorite ();
910
use MetaCPAN::Script::First ();
@@ -226,6 +227,14 @@ sub index_mirrors {
226227
'index mirrors' );
227228
}
228229

230+
sub index_cover {
231+
my $self = shift;
232+
233+
local @ARGV = ( 'cover', '--json_file', 't/var/cover.json' );
234+
ok( MetaCPAN::Script::Cover->new_with_options( $self->_config )->run,
235+
'index cover' );
236+
}
237+
229238
sub index_permissions {
230239
my $self = shift;
231240

0 commit comments

Comments
 (0)