File Coverage

blib/lib/Test/MasterData/Declare.pm
Criterion Covered Total %
statement 150 157 95.5
branch 18 26 69.2
condition 14 27 51.8
subroutine 37 38 97.3
pod 7 10 70.0
total 226 258 87.6


line stmt bran cond sub pod time code
1             package Test::MasterData::Declare;
2 4     4   422561 use 5.010001;
  4         48  
3 4     4   31 use strict;
  4         8  
  4         123  
4 4     4   27 use warnings;
  4         17  
  4         149  
5 4     4   1606 use utf8;
  4         56  
  4         27  
6              
7             our $VERSION = "0.02";
8              
9 4     4   260 use Test2::API qw/context/;
  4         12  
  4         249  
10 4     4   1098 use Test2::V0;
  4         435231  
  4         28  
11 4     4   6007 use Test2::Compare ();
  4         14  
  4         120  
12 4     4   30 use Test2::Tools::Compare qw/number/;
  4         11  
  4         235  
13 4     4   34 use Test2::Compare::Custom;
  4         11  
  4         147  
14 4     4   32 use Test2::Compare::String;
  4         11  
  4         159  
15 4     4   36 use Scalar::Util qw/blessed/;
  4         12  
  4         235  
16              
17 4     4   32 use Carp qw/croak/;
  4         15  
  4         354  
18              
19             %Carp::Internal = (
20             %Carp::Internal,
21             "Test::MasterData::Declare" => 1,
22             "Test::MasterData::Declare::Compare::RowHash" => 1,
23             "Test::MasterData::Declare::Compare::RowCustrom" => 1,
24             "Test::MasterData::Declare::Row" => 1,
25             );
26              
27 4     4   33 use parent "Exporter";
  4         12  
  4         43  
28             our @EXPORT = qw/
29             master_data
30             load_csv
31             table
32             expect_row
33             relation
34              
35             like_number
36             if_column
37             json
38             /;
39              
40             our $DEFAULT_IDENTIFIER_KEY = "id";
41              
42 4     4   2361 use Test::MasterData::Declare::Runner;
  4         19  
  4         172  
43 4     4   1615 use Test::MasterData::Declare::Reader;
  4         20  
  4         190  
44 4     4   1656 use Test::MasterData::Declare::Compare::RowHash;
  4         13  
  4         130  
45 4     4   1234 use Test::MasterData::Declare::Compare::RowCustom;
  4         13  
  4         6106  
46              
47             my $runner;
48              
49             sub master_data (&) {
50 3     3 1 365 my $code = shift;
51              
52 3         42 $runner = Test::MasterData::Declare::Runner->new(
53             code => $code,
54             );
55              
56 3         50 $runner->run;
57              
58 3         301 $runner = undef;
59             }
60              
61             sub load_csv {
62 3     3 1 60 my %paths = @_;
63 3   33     27 my $identifier_key = delete $paths{_identifier_key} || $DEFAULT_IDENTIFIER_KEY;
64              
65 3         16 for my $table_name (keys %paths) {
66 5         56 my $filepath = $paths{$table_name};
67 5         47 my $reader = Test::MasterData::Declare::Reader->read_csv_from(
68             table_name => $table_name,
69             filepath => $filepath,
70             identifier_key => $identifier_key,
71             );
72              
73 5         299 $runner->add_reader_to_bucket($reader);
74             }
75             }
76              
77             sub row_hash (&) {
78 4     4 0 26 Test2::Compare::build("Test::MasterData::Declare::Compare::RowHash", @_)
79             }
80              
81             sub row_json {
82 2     2 0 71 my ($column, @keys) = @_;
83 2         14 my $check = pop @keys;
84              
85 2         9 my $build = Test2::Compare::get_build();
86 2 50       21 croak "row_json must be with-in Test::MasterData::Declare::Compare::RowHash"
87             unless $build->isa("Test::MasterData::Declare::Compare::RowHash");
88              
89 2         15 $build->add_json_field($column, @keys, $check);
90             }
91              
92             sub table {
93 4     4 1 23 my ($table_name, $column, @filters_or_expects) = @_;
94 4         18 my $ctx = context();
95              
96 4         476 my $rows = $runner->rows($table_name);
97             like $rows, array {
98 4     4   542 for my $fe (@filters_or_expects) {
99 6 100 66     114 if (blessed $fe && $fe->isa("Test2::Compare::Base")) {
    50          
100             all_items
101             row_hash {
102 3         351 field $column => $fe;
103 3         25 };
104             }
105             elsif (ref $fe eq "CODE") {
106 3         12 $fe->($column);
107             }
108             }
109 4         60 };
110              
111 4         11883 $ctx->release;
112             }
113              
114             sub like_number {
115 4     4 1 15333 my ($begin, @funcs) = @_;
116              
117 4 100 66     41 my $end = $funcs[0] && number($funcs[0]) ? shift @funcs : $begin;
118              
119              
120 4         324 my $operator = "$begin <= ... <= $end";
121 4         14 my $name = "Between";
122 4 100       22 if ($begin == $end) {
123 1         4 $operator = "$begin == ...";
124 1         4 $name = "Equal";
125             }
126              
127             my $cus = Test2::Compare::Custom->new(
128             name => $name,,
129             operator => $operator,
130             code => sub {
131 10     10   589 my %args = @_;
132 10 50       42 return 0 unless number($args{got});
133              
134 10 100 66     680 return $begin <= $args{got} && $args{got} <= $end ? 1 : 0;
135             },
136 4         53 );
137              
138 4         209 return $cus, @funcs;
139             }
140              
141             sub if_column {
142 2     2 1 12 my ($column, $cond, @funcs) = @_;
143              
144 2         6 my $filter;
145 2 50       8 if (ref $column eq "CODE") {
146             $filter = sub {
147 0     0   0 my @rows = @_;
148 0         0 my @filtered;
149 0         0 for my $row (@rows) {
150 0 0       0 push @filtered, $row if $column->($row->row);
151             }
152 0         0 return @filtered;
153 0         0 };
154             }
155             else {
156             $filter = sub {
157 2     2   754 my @rows = @_;
158 2         7 my @filtered;
159 2         7 for my $row (@rows) {
160             my $delta = Test2::Compare::compare(
161 6         34 $row->row->{$column},
162             $cond,
163             \&Test2::Compare::relaxed_convert,
164             );
165 6 100       1279 push @filtered, $row unless $delta;
166             }
167 2         13 return @filtered;
168 2         15 };
169             }
170              
171             return sub {
172 2     2   10 my $array = Test2::Compare::get_build();
173 2         45 $array->add_filter($filter);
174 2         17 }, @funcs;
175             }
176              
177             sub json {
178 1     1 1 5 my ($key, @funcs) = @_;
179              
180 1         4 my @keys = ($key);
181 1   33     15 while (scalar(@funcs) > 0 && !blessed $funcs[0] && ref $funcs[0] ne "CODE") {
      33        
182 0         0 push @keys, shift @funcs;
183             }
184              
185             return sub {
186 1     1   3 my $column = shift;
187 1         5 my $ctx = context();
188             all_items
189             row_hash {
190 1         106 for my $f (@funcs) {
191 2 100 66     25 if (blessed $f && $f->isa("Test2::Compare::Base")) {
    50          
192 1         7 row_json $column, @keys => $f;
193             }
194             elsif (ref $f eq "CODE") {
195             row_json $column, @keys => validator(sub {
196 3         128 my %args = @_;
197 3         8 my $got = $args{got};
198 3         31 $f->($got);
199 1         13 });
200             }
201             }
202 1         104 };
203 1         62 $ctx->release;
204 1         10 };
205             }
206              
207             sub expect_row {
208 1     1 0 25 my ($table_name, $func) = @_;
209              
210 1         6 my $ctx = context();
211              
212             my $check = Test::MasterData::Declare::Compare::RowCustrom->new(
213             code => sub {
214 3     3   34 my %args = @_;
215 3         5 my $got = $args{got};
216 3         9 $func->($got);
217             },
218 1         129 );
219              
220 1         47 my $rows = $runner->rows($table_name);
221             like $rows, array {
222 1     1   86 all_items $check;
223 1         8 };
224              
225 1         142 $ctx->release;
226             }
227              
228             sub relation {
229 1     1 1 30 my ($from_table, $to_table, @opts) = @_;
230              
231 1         3 my %conds;
232 1   66     14 while (!ref $opts[0] && scalar(@opts) >= 2) {
233 1         5 my $from_table_column = shift @opts;
234 1         4 my $to_table_column = shift @opts;
235 1         8 $conds{$from_table_column} = $to_table_column;
236             }
237              
238 1         9 my $from_rows = $runner->rows($from_table);
239 1         6 my $to_rows = $runner->rows($to_table);
240             my $to_rows_selector = sub {
241 3     3   24 my %from_row_values = @_;
242              
243             my @matched_rows = grep {
244 3         12 my $row = $_->row;
  9         32  
245             grep {
246 9         31 defined $from_row_values{$_} &&
247             defined $row->{$conds{$_}} &&
248 9 50 33     97 $from_row_values{$_} eq $row->{$conds{$_}}
249             } keys %conds;
250             } @$to_rows;
251              
252 3         15 return @matched_rows;
253 1         10 };
254              
255              
256             my $check = Test::MasterData::Declare::Compare::RowCustrom->new(
257             name => "HasRelation",,
258             operator => "$from_table has $to_table",
259             code => sub {
260 3     3   59 my %args = @_;
261 3         10 my $got = $args{got};
262 3         13 my @matched_rows = $to_rows_selector->(%$got);
263              
264 3         19 return scalar(@matched_rows) > 0;
265             },
266 1         44 );
267              
268 1         79 my $ctx = context();
269             like $from_rows, array {
270 1     1   176 all_items $check;
271 1         182 };
272 1         409 $ctx->release;
273             }
274              
275             1;
276             __END__