File Coverage

blib/lib/Yaadgom.pm
Criterion Covered Total %
statement 136 157 86.6
branch 21 40 52.5
condition 7 10 70.0
subroutine 20 21 95.2
pod 3 5 60.0
total 187 233 80.2


line stmt bran cond sub pod time code
1 3     3   1923 use strict;
  3         8  
  3         103  
2              
3             package Yaadgom;
4 3     3   67 use 5.008_005;
  3         11  
5             our $VERSION = '0.08';
6 3     3   1766 use Moo;
  3         37605  
  3         20  
7 3     3   4375 use Devel::GlobalDestruction;
  3         10  
  3         26  
8              
9 3     3   1966 use Encode qw/decode/;
  3         30695  
  3         290  
10 3     3   33 use JSON::MaybeXS;
  3         9  
  3         226  
11 3     3   24 use URI;
  3         6  
  3         103  
12 3     3   19 use Carp;
  3         8  
  3         178  
13 3     3   1461 use Class::Trigger;
  3         3940  
  3         19  
14              
15             has '_json_ed' => (
16             is => 'rw',
17             lazy => 1,
18             builder => '_build_json'
19             );
20              
21             sub _build_json {
22 3     3   4662 JSON::MaybeXS->new( utf8 => 1, pretty => 1, canonical => 1 );
23             }
24              
25             has 'slash_filename_replacement' => ( is => 'rw', default => sub { '-' } );
26              
27             has '_results' => ( is => 'rw', default => sub { +{} } );
28             has 'file_name' => ( is => 'rw', default => sub { $0 } );
29              
30             sub process_response {
31 3     3 1 26921 my ( $self, %opt ) = @_;
32              
33 3         13 my $req = $opt{req};
34 3         9 my $res = $opt{res};
35              
36 3         13 for my $obj (qw/res req/) {
37 6 100       28 for my $func ( qw/as_string/, ( $obj eq 'req' ? qw/uri/ : () ) ) {
38 9         24 eval { $opt{$obj}->$func };
  9         64  
39 9 50       1024 croak "Param{$obj}->$func() died, perhaps you forgot to pass an HTTP object: \n$@" if $@;
40             }
41             }
42              
43 3         45 my $rep = $self->slash_filename_replacement;
44              
45 3 50       19 my $file = exists $opt{file} ? $opt{file} : undef;
46              
47 3 50       16 if ($file) {
48 0         0 $file =~ s/^\///;
49 0         0 $file =~ s/\/$//;
50             }
51             else {
52 3         19 $file = URI->new( $req->uri->path )->path;
53              
54 3         465 $file =~ s/^\///;
55 3         12 $file =~ s/\/$//;
56 3         10 $file =~ s/\//$rep/gio;
57 3         13 $file =~ s/[0-9]+/*/go;
58 3         83 $file =~ s/[^a-z$rep*]//gio;
59              
60 3         36 $self->call_trigger( 'filename_generated', { req => $req, file => $file } );
61 3         381 my @results = @{ $self->last_trigger_results };
  3         17  
62 3 50       38 ($file) = @{ $results[-1] } if $results[-1];
  0         0  
63             }
64              
65 3 50 33     22 my $weight = defined $opt{weight} && $opt{weight} =~ /^[0-9]+$/ ? $opt{weight} : 1;
66              
67 3         100 push @{ $self->_results->{$file}{$weight} },
68             {
69             extra => $opt{extra},
70             file => $file,
71 3   100     9 folder => $opt{folder} || 'default',
72             markdown => $self->get_markdown(%opt)
73             };
74              
75             }
76              
77             sub _write_title {
78 3     3   11 my ( $self, $title ) = @_;
79 3         49 "\n## $title\n\n";
80             }
81              
82             sub _write_subtitle {
83 6     6   20 my ( $self, $title ) = @_;
84 6         37 "\n### $title\n\n";
85             }
86              
87             sub _write_line {
88 0     0   0 my ( $self, $title ) = @_;
89 0         0 my $str = "$title\n";
90             }
91              
92             sub _write_preformated {
93 6     6   17 my ( $self, $str ) = @_;
94 6         35 "
$str\n
\n";
95             }
96              
97             sub format_body {
98 6     6 0 512 my ( $self, $str ) = @_;
99 6         31 my ( $header, $body ) = split /\n\n/, $str;
100 6 100 66     45 if ( $header =~ /application\/json/ && $body ) {
101 3         95 $body = $self->_json_ed->encode( $self->_json_ed->decode($body) );
102 3         385 $body = decode( 'utf8', $body );
103             }
104              
105 6         307 $self->call_trigger( 'format_body', { response_str => $body } );
106 6         407 my @results = @{ $self->last_trigger_results };
  6         25  
107 6 50       56 ($body) = @{ $results[-1] } if $results[-1];
  0         0  
108              
109 6         41 return "$header\n\n$body";
110             }
111              
112             sub get_markdown {
113 3     3 0 15 my ( $self, %opt ) = @_;
114              
115 3         46 my $file_name = $self->file_name;
116              
117 3         9 my $req = $opt{req};
118 3         8 my $res = $opt{res};
119              
120 3 50       14 my $desc = join ' ', $req->method, $req->uri->path, $opt{extra}{is_fail} ? ' + expected failure' : '';
121              
122 3         140 do {
123 3         19 $self->call_trigger( 'format_title', { title => $desc } );
124 3         243 my @results = @{ $self->last_trigger_results };
  3         11  
125 3 50       59 ($desc) = @{ $results[-1] } if $results[-1];
  0         0  
126             };
127              
128             my $str = join '',
129             $self->_write_title($desc),
130             ( defined $file_name ? "$file_name\n" : '' ),
131 3 50       18 ( exists $opt{extra}{name} ? ( $self->_write_line( '> ' . $opt{extra}{name} . "\n" ) ) : () ),
    50          
132             $self->_write_subtitle('Request'),
133             $self->_write_preformated( $self->format_body( $req->as_string ) ),
134             $self->_write_subtitle('Response'),
135             $self->_write_preformated( $self->format_body( $res->as_string ) );
136              
137 3         12 do {
138 3         20 $self->call_trigger( 'format_before_extras', { str => $str } );
139 3         294 my @results = @{ $self->last_trigger_results };
  3         15  
140 3 50       34 ($str) = @{ $results[-1] } if $results[-1];
  0         0  
141             };
142              
143 3         8 do {
144 3         22 $self->call_trigger( 'process_extras', %opt );
145 3         259 my @results = @{ $self->last_trigger_results };
  3         13  
146 3         29 $str .= join '', $_ for @results;
147             };
148              
149 3 50       17 if ( exists $opt{extra}{fields} ) {
150 0         0 $str .= $self->_write_subtitle('Fields details');
151 0         0 while ( my ( $key, $maybealist ) = each %{ $opt{extra}{fields} } ) {
  0         0  
152              
153 0         0 $str .= $self->_write_line( '#### ' . $key );
154 0 0       0 if ( ref $maybealist eq 'ARRAY' ) {
155 0         0 $str .= $self->_write_line( '* ' . $_ ) for @$maybealist;
156 0         0 $str .= "\n";
157             }
158             else {
159 0         0 $str .= $self->_write_line( '- ' . $maybealist );
160 0         0 $str .= "\n";
161             }
162             }
163             }
164              
165 3         6 do {
166 3         18 $self->call_trigger( 'format_after_extras', { str => $str } );
167 3         229 my @results = @{ $self->last_trigger_results };
  3         13  
168 3 50       33 ($str) = @{ $results[-1] } if $results[-1];
  0         0  
169             };
170              
171 3         30 return $str;
172             }
173              
174             sub export_to_dir {
175 1     1 1 499 my ( $self, %conf ) = @_;
176              
177 1         11 my $dir = $conf{dir};
178 1 50       24 croak "dir ($dir) is not an directory" unless -d $dir;
179              
180             $self->map_results(
181             sub {
182 1     1   7 my (%info) = @_;
183              
184 1         3 my $str = $info{str};
185 1         3 my $folder = $info{folder};
186 1         6 my $file = $dir . '/' . $folder . '/' . $info{file} . '.md';
187              
188 1         61 mkdir $dir . '/' . $folder;
189              
190 1 50       101 open my $fh, '>>:utf8', $file or croak "cant open file $file $!";
191 1         23 print $fh $str;
192 1         65 close $fh;
193             }
194 1         15 );
195              
196 1         14 return 1;
197             }
198              
199             sub map_results {
200 3     3 1 63 my ( $self, $callback ) = @_;
201              
202 3         15 my $tests = $self->_results;
203              
204 3         14 foreach my $endpoint ( keys %$tests ) {
205              
206 3         13 my @in_order;
207 3         7 foreach my $num ( sort { $a <=> $b } keys %{ $tests->{$endpoint} } ) {
  0         0  
  3         16  
208 3         8 push @in_order, @{ $tests->{$endpoint}{$num} };
  3         14  
209             }
210              
211 3         10 my $folders = {};
212              
213 3         11 foreach (@in_order) {
214 3         7 push @{ $folders->{ $_->{folder} }{ $_->{file} } }, $_;
  3         19  
215             }
216              
217 3         14 for my $folder ( keys %$folders ) {
218 3         8 for my $file ( keys %{ $folders->{$folder} } ) {
  3         15  
219              
220 3         10 my $str = join "\n
\n", map { $_->{markdown} } @{ $folders->{$folder}{$file} };
  3         21  
  3         11  
221              
222 3         89 my $format_time = "\ngenerated at " . gmtime(time) . " GMT\n";
223 3         11 do {
224 3         21 $self->call_trigger( 'format_generated_str', { str => $format_time } );
225 3         249 my @results = @{ $self->last_trigger_results };
  3         14  
226 3 50       34 ($format_time) = @{ $results[-1] } if $results[-1];
  0         0  
227             };
228              
229 3         17 $str .= $format_time;
230              
231 3   100     31 $callback->(
232             folder => $folder,
233             file => $file || '_index',
234             str => $str
235             );
236              
237             }
238             }
239              
240             }
241              
242             }
243              
244             has 'on_destroy' => ( is => 'rw' );
245              
246             sub DESTROY {
247 3     3   3543 my $self = shift;
248              
249 3 50       157 if ( ref $self->on_destroy eq 'CODE' ) {
250 0           $self->on_destroy->($self);
251             }
252              
253             }
254              
255             1;
256              
257             __END__