File Coverage

lib/Test/Neo4j/Types.pm
Criterion Covered Total %
statement 335 335 100.0
branch 9 10 90.0
condition 6 18 33.3
subroutine 42 42 100.0
pod 6 6 100.0
total 398 411 96.8


line stmt bran cond sub pod time code
1 3     3   212799 use v5.10;
  3         47  
2 3     3   17 use strict;
  3         5  
  3         62  
3 3     3   19 use warnings;
  3         4  
  3         153  
4              
5             package Test::Neo4j::Types;
6             # ABSTRACT: Tools for testing Neo4j type modules
7             $Test::Neo4j::Types::VERSION = '0.03';
8              
9 3     3   16 use Test::More 0.94;
  3         38  
  3         25  
10 3     3   2372 use Test::Exception;
  3         10076  
  3         9  
11 3     3   2304 use Test::Warnings qw(warnings :no_end_test);
  3         6057  
  3         24  
12              
13 3     3   380 use Exporter 'import';
  3         7  
  3         154  
14 3     3   118 BEGIN { our @EXPORT = qw(
15             neo4j_node_ok
16             neo4j_relationship_ok
17             neo4j_path_ok
18             neo4j_point_ok
19             neo4j_datetime_ok
20             neo4j_duration_ok
21             )}
22              
23             {
24             # This happens within new versions of Neo4j/Types.pm,
25             # but we can't be sure the version is new enough:
26             package # local
27             Neo4j::Types;
28 3     3   57 use warnings::register;
  3         6  
  3         1387  
29             }
30              
31              
32             sub _element_id_test {
33 12     12   36 my ($BOTH, $ID_ONLY, $new, $class, $prefix) = @_;
34            
35             subtest "${prefix}element_id", sub {
36 12     12   9886 plan tests => 6;
37            
38 12         7647 my $both = $new->($class, {%$BOTH});
39 12         129 my $id_only = $new->($class, {%$ID_ONLY});
40 12 100       170 lives_ok { $both->element_id } 'optional op element_id' if $both->can('element_id');
  4         139  
41 12 100       1798 dies_ok { $both->element_id } 'optional op element_id' if ! $both->can('element_id');
  8         347  
42             SKIP: {
43 12 100       3000 skip 'optional op element_id unimplemented', 2+3 unless $class->can('element_id');
  12         103  
44 3     3   22 no strict 'refs';
  3         4  
  3         611  
45 4         8 my ($element_id, $id) = map { "$prefix$_" } qw( element_id id );
  8         24  
46            
47             # When both IDs are present, id() MAY warn
48 4         14 is $both->$element_id(), $BOTH->{$element_id}, "$element_id";
49 4         1542 warnings { is $both->$id(), $BOTH->{$id}, "legacy $id" };
  4         61  
50            
51             # For a missing element ID, element_id() returns the numeric ID and MUST warn
52 4         1745 my @w_eid = warnings { is $id_only->$element_id(), $ID_ONLY->{$id}, "no $element_id with legacy $id" };
  4         53  
53 4         1603 ok @w_eid, "no $element_id warns";
54 4 50       1544 warn @w_eid if @w_eid > 1;
55 3     3   21 no warnings 'Neo4j::Types';
  3         5  
  3         11173  
56 4         26 is warnings { $id_only->$element_id() }, @w_eid - 1, "no $element_id warn cat is Neo4j::Types";
  4         51  
57             };
58 12         99 };
59             }
60              
61              
62             sub _node_test {
63 3     3   20 my ($node_class, $new) = @_;
64            
65 3         11 plan tests => 12 + 5 + 7 + 1 + 1;
66            
67 3         1914 my ($n, @l, $p);
68            
69 3         30 $n = $new->($node_class, my $id_only = {
70             id => 42,
71             labels => ['Foo', 'Bar'],
72             properties => { foofoo => 11, barbar => 22, '123' => [1, 2, 3] },
73             });
74 3         37 is $n->id(), 42, 'id';
75 3         1277 @l = $n->labels;
76 3         57 is scalar(@l), 2, 'label count';
77 3         1120 is $l[0], 'Foo', 'label Foo';
78 3         1162 is $l[1], 'Bar', 'label Bar';
79 3     3   1102 lives_and { is scalar($n->labels), 2 } 'scalar context';
  3         56  
80 3         1149 is $n->get('foofoo'), 11, 'get foofoo';
81 3         1496 is $n->get('barbar'), 22, 'get barbar';
82 3         1080 is_deeply $n->get('123'), [1, 2, 3], 'get 123';
83 3         1944 $p = $n->properties;
84 3         23 is ref($p), 'HASH', 'props ref';
85 3         1095 is $p->{foofoo}, 11, 'props foofoo';
86 3         1125 is $p->{barbar}, 22, 'props barbar';
87 3         1094 is_deeply $p->{123}, [1, 2, 3], 'props 123';
88            
89 3         1772 $n = $new->($node_class, {
90             id => 0,
91             properties => { '0' => [] },
92             });
93 3         52 is $n->id(), 0, 'id 0';
94 3         1090 is ref($n->get('0')), 'ARRAY', 'get 0 ref';
95 3         1067 is scalar(@{$n->get('0')}), 0, 'get 0 empty';
  3         15  
96 3         1085 $p = $n->properties;
97 3         27 is_deeply $p, {0=>[]}, 'props deeply';
98 3         2183 is_deeply [$n->properties], [{0=>[]}], 'props list context';
99            
100 3         2647 $n = $new->($node_class, { });
101 3         43 ok ! defined($n->id), 'id gigo';
102 3         1108 @l = $n->labels;
103 3         57 is scalar(@l), 0, 'no labels';
104 3     3   1138 lives_and { is scalar($n->labels), 0 } 'scalar context no labels';
  3         50  
105 3         1118 $p = $n->properties;
106 3         26 is ref($p), 'HASH', 'empty props ref';
107 3         1080 is scalar(keys %$p), 0, 'empty props empty';
108 3         1081 is_deeply [$n->get('whatever')], [undef], 'prop undef';
109 3         1716 ok ! exists $n->properties->{whatever}, 'prop remains non-existent';
110            
111             # element ID
112 3         1019 my $both = { element_id => 'e17', id => 17 };
113 3         13 _element_id_test($both, $id_only, $new, $node_class, '');
114            
115 3         8611 ok $n->DOES('Neo4j::Types::Node'), 'does role';
116             }
117              
118              
119             sub neo4j_node_ok {
120 3     3 1 2641 my ($class, $new, $name) = @_;
121 3   33     28 $name //= "neo4j_node_ok '$class'";
122 3     3   19 subtest $name, sub { _node_test($class, $new) };
  3         2649  
123             }
124              
125              
126             sub _relationship_test {
127 3     3   26 my ($rel_class, $new) = @_;
128            
129 3         12 plan tests => 11 + 5 + 8 + 3 + 1;
130            
131 3         1766 my ($r, $p);
132            
133 3         40 $r = $new->($rel_class, my $id_only = {
134             id => 55,
135             type => 'TEST',
136             start_id => 34,
137             end_id => 89,
138             properties => { foo => 144, bar => 233, '358' => [3, 5, 8] },
139             });
140 3         53 is $r->id, 55, 'id';
141 3         1123 is $r->type, 'TEST', 'type';
142 3         1123 is $r->start_id, 34, 'start id';
143 3         1065 is $r->end_id, 89, 'end id';
144 3         1184 is $r->get('foo'), 144, 'get foo';
145 3         1078 is $r->get('bar'), 233, 'get bar';
146 3         1096 is_deeply $r->get('358'), [3, 5, 8], 'get 358';
147 3         1793 $p = $r->properties;
148 3         32 is ref($p), 'HASH', 'props ref';
149 3         1076 is $p->{foo}, 144, 'props foo';
150 3         1069 is $p->{bar}, 233, 'props bar';
151 3         1140 is_deeply $p->{358}, [3, 5, 8], 'props 358';
152            
153 3         1806 $r = $new->($rel_class, {
154             id => 0,
155             properties => { '0' => [] },
156             });
157 3         56 is $r->id(), 0, 'id 0';
158 3         1119 is ref($r->get('0')), 'ARRAY', 'get 0 ref';
159 3         1075 is scalar(@{$r->get('0')}), 0, 'get 0 empty';
  3         14  
160 3         1121 $p = $r->properties;
161 3         29 is_deeply $p, {0=>[]}, 'props deeply';
162 3         2116 is_deeply [$r->properties], [{0=>[]}], 'props list context';
163            
164 3         2584 $r = $new->($rel_class, { });
165 3         37 ok ! defined($r->id), 'id gigo';
166 3         1084 ok ! defined($r->type), 'no type';
167 3         1016 ok ! defined($r->start_id), 'no start id';
168 3         1035 ok ! defined($r->end_id), 'no end id';
169 3         1055 $p = $r->properties;
170 3         26 is ref($p), 'HASH', 'empty props ref';
171 3         1142 is scalar(keys %$p), 0, 'empty props empty';
172 3         1117 is_deeply [$r->get('whatever')], [undef], 'prop undef';
173 3         1717 ok ! exists $r->properties->{whatever}, 'prop remains non-existent';
174            
175             # element ID
176 3         1039 my $both = {
177             element_id => 'e60', id => 60,
178             start_element_id => 'e61', start_id => 61,
179             end_element_id => 'e62', end_id => 62,
180             };
181 3         14 _element_id_test($both, $id_only, $new, $rel_class, '');
182 3         7820 _element_id_test($both, $id_only, $new, $rel_class, 'start_');
183 3         7799 _element_id_test($both, $id_only, $new, $rel_class, 'end_');
184            
185 3         7739 ok $r->DOES('Neo4j::Types::Relationship'), 'does role';
186             }
187              
188              
189             sub neo4j_relationship_ok {
190 3     3 1 4066 my ($class, $new, $name) = @_;
191 3   33     28 $name //= "neo4j_relationship_ok '$class'";
192 3     3   15 subtest $name, sub { _relationship_test($class, $new) };
  3         2208  
193             }
194              
195              
196             sub _path_test {
197 2     2   6 my ($path_class, $new) = @_;
198            
199 2         8 plan tests => 3 + 3 + 6 + 6 + 1;
200            
201 2         1135 my (@p, $p, @e);
202            
203             my $new_path = sub {
204 6     6   11 my $i = 0;
205 6 100       13 map { my $o = $_; bless \$o, 'Test::Neo4j::Types::Path' . ($i++ & 1 ? 'Rel' : 'Node') } @_;
  18         23  
  18         74  
206 2         20 };
207            
208 2         9 @p = $new_path->( \6, \7, \8 );
209 2         34 $p = $new->($path_class, \@p);
210 2         22 @e = $p->elements;
211 2         59 is_deeply [@e], [@p], 'deeply elements 3';
212 2         2083 @e = $p->nodes;
213 2         65 is_deeply [@e], [$p[0],$p[2]], 'deeply nodes 2';
214 2         1625 @e = $p->relationships;
215 2         47 is_deeply [@e], [$p[1]], 'deeply rel 1';
216            
217 2         1420 @p = $new_path->( \9 );
218 2         11 $p = $new->($path_class, \@p);
219 2         21 @e = $p->elements;
220 2         32 is_deeply [@e], [@p], 'deeply elements 1';
221 2         1343 @e = $p->nodes;
222 2         27 is_deeply [@e], [$p[0]], 'deeply nodes 1';
223 2         1360 @e = $p->relationships;
224 2         26 is_deeply [@e], [], 'deeply rel 0';
225            
226 2         1105 @p = $new_path->( \1, \2, \3, \4, \5 );
227 2         9 $p = $new->($path_class, \@p);
228 2         16 @e = $p->elements;
229 2         35 is_deeply [@e], [@p], 'deeply elements 5';
230 2     2   2375 lives_and { is scalar($p->elements), 5 } 'scalar context elements';
  2         40  
231 2         778 @e = $p->nodes;
232 2         85 is_deeply [@e], [$p[0],$p[2],$p[4]], 'deeply nodes 3';
233 2     2   1861 lives_and { is scalar($p->nodes), 3 } 'scalar context nodes';
  2         40  
234 2         774 @e = $p->relationships;
235 2         32 is_deeply [@e], [$p[1],$p[3]], 'deeply rel 2';
236 2     2   1655 lives_and { is scalar($p->relationships), 2 } 'scalar context relationships';
  2         54  
237            
238 2         758 $p = $new->($path_class, []);
239 2         26 @e = $p->elements;
240 2         25 is scalar(@e), 0, 'no elements gigo';
241 2     2   751 lives_and { is scalar($p->elements), 0 } 'scalar context no elements';
  2         38  
242 2         743 @e = $p->nodes;
243 2         20 is scalar(@e), 0, 'no nodes 0 gigo';
244 2     2   736 lives_and { is scalar($p->nodes), 0 } 'scalar context no nodes';
  2         29  
245 2         746 @e = $p->relationships;
246 2         22 is scalar(@e), 0, 'no relationships 0 gigo';
247 2     2   722 lives_and { is scalar($p->relationships), 0 } 'scalar context no relationships';
  2         76  
248            
249 2         762 ok $p->DOES('Neo4j::Types::Path'), 'does role';
250             }
251              
252              
253             sub neo4j_path_ok {
254 2     2 1 2687 my ($class, $new, $name) = @_;
255 2   33     17 $name //= "neo4j_path_ok '$class'";
256 2     2   11 subtest $name, sub { _path_test($class, $new) };
  2         1428  
257             }
258              
259              
260             sub _point_test {
261 2     2   17 my ($point_class, $new) = @_;
262            
263 2         9 plan tests => 3+3 + 3+3+3+3+2 + 1;
264            
265 2         1142 my (@c, $p);
266            
267            
268             # Simple point, location in real world
269 2         12 @c = ( 2.294, 48.858, 396 );
270 2         13 $p = $new->( $point_class, { srid => 4979, coordinates => [@c] });
271 2         32 is $p->srid(), 4979, 'eiffel srid';
272 2         742 is_deeply [$p->coordinates], [@c], 'eiffel coords';
273 2         1302 is scalar ($p->coordinates), 3, 'scalar context eiffel coords';
274            
275 2         730 @c = ( 2.294, 48.858 );
276 2         16 $p = $new->( $point_class, { srid => 4326, coordinates => [@c] });
277 2         39 is $p->srid(), 4326, 'eiffel 2d srid';
278 2         771 is_deeply [$p->coordinates], [@c], 'eiffel 2d coords';
279 2         1189 is scalar ($p->coordinates), 2, 'scalar context eiffel 2d coords';
280            
281            
282             # Other SRSs, location not in real world
283 2         740 @c = ( 12, 34 );
284 2         16 $p = $new->( $point_class, { srid => 7203, coordinates => [@c] });
285 2         23 is $p->srid(), 7203, 'plane srid';
286 2         731 is_deeply [$p->coordinates], [@c], 'plane coords';
287 2         1229 is scalar ($p->coordinates), 2, 'scalar context plane coords';
288            
289 2         720 @c = ( 56, 78, 90 );
290 2         18 $p = $new->( $point_class, { srid => 9157, coordinates => [@c] });
291 2         20 is $p->srid(), 9157, 'space srid';
292 2         806 is_deeply [$p->coordinates], [@c], 'space coords';
293 2         1217 is scalar ($p->coordinates), 3, 'scalar context space coords';
294            
295 2         723 @c = ( 361, -91 );
296 2         13 $p = $new->( $point_class, { srid => 4326, coordinates => [@c] });
297 2         20 is $p->srid(), 4326, 'ootw srid';
298 2         715 is_deeply [$p->coordinates], [@c], 'ootw coords';
299 2         1141 is scalar ($p->coordinates), 2, 'scalar context ootw coords';
300            
301 2         723 @c = ( 'what', 'ever' );
302 2         13 $p = $new->( $point_class, { srid => '4326', coordinates => [@c] });
303 2         20 is $p->srid(), '4326', 'string srid';
304 2         733 is_deeply [$p->coordinates], [@c], 'string coords';
305 2         1230 is scalar ($p->coordinates), 2, 'scalar context string coords';
306            
307 2         734 @c = ( undef, 45 );
308 2         16 $p = $new->( $point_class, { srid => 7203, coordinates => [@c] });
309 2         23 is_deeply [$p->coordinates], [@c], 'undef coord';
310 2         1186 is scalar ($p->coordinates), 2, 'scalar context undef coord';
311            
312            
313 2         758 ok $p->DOES('Neo4j::Types::Point'), 'does role';
314             }
315              
316              
317             sub neo4j_point_ok {
318 2     2 1 2653 my ($class, $new, $name) = @_;
319 2   33     20 $name //= "neo4j_point_ok '$class'";
320 2     2   11 subtest $name, sub { _point_test($class, $new) };
  2         1459  
321             }
322              
323              
324             sub _datetime_test {
325 1     1   2 my ($datetime_class, $new) = @_;
326            
327 1         6 plan tests => 8 * 7 + 1;
328            
329 1         547 my ($dt, $p, $type);
330            
331 1         2 $type = 'DATE';
332 1         8 $dt = $new->($datetime_class, $p = {
333             days => 18645, # 2021-01-18
334             });
335 1         17 is $dt->days, $p->{days}, 'date: days';
336 1         362 is $dt->epoch, 1610928000, 'date: epoch';
337 1         357 is $dt->nanoseconds, $p->{nanoseconds}, 'date: no nanoseconds';
338 1         416 is $dt->seconds, $p->{seconds}, 'date: no seconds';
339 1         455 is $dt->type, $type, 'date: type';
340 1         358 is $dt->tz_name, $p->{tz_name}, 'date: no tz_name';
341 1         428 is $dt->tz_offset, $p->{tz_offset}, 'date: no tz_offset';
342            
343 1         409 $type = 'LOCAL TIME';
344 1         6 $dt = $new->($datetime_class, $p = {
345             nanoseconds => 1,
346             });
347 1         13 is $dt->days, $p->{days}, 'local time: no days';
348 1         411 is $dt->epoch, 0, 'local time: epoch';
349 1         353 is $dt->nanoseconds, $p->{nanoseconds}, 'local time: nanoseconds';
350 1         352 is $dt->seconds, 0, 'local time: seconds';
351 1         386 is $dt->type, $type, 'local time: type';
352 1         353 is $dt->tz_name, $p->{tz_name}, 'local time: no tz_name';
353 1         416 is $dt->tz_offset, $p->{tz_offset}, 'local time: no tz_offset';
354            
355 1         427 $type = 'ZONED TIME';
356 1         7 $dt = $new->($datetime_class, $p = {
357             seconds => 86340, # 23:59
358             nanoseconds => 5e8, # 0.5 s
359             tz_offset => -28800, # -8 h
360             });
361 1         10 is $dt->days, $p->{days}, 'zoned time: no days';
362 1         415 is $dt->epoch, 86340, 'zoned time: epoch';
363 1         360 is $dt->nanoseconds, $p->{nanoseconds}, 'zoned time: nanoseconds';
364 1         355 is $dt->seconds, $p->{seconds}, 'zoned time: seconds';
365 1         367 is $dt->type, $type, 'zoned time: type';
366 1         362 is $dt->tz_name, 'Etc/GMT+8', 'zoned time: tz_name';
367 1         365 is $dt->tz_offset, $p->{tz_offset}, 'zoned time: tz_offset';
368            
369 1         366 $type = 'LOCAL DATETIME';
370 1         7 $dt = $new->($datetime_class, $p = {
371             days => -1,
372             seconds => 86399,
373             });
374 1         12 is $dt->days, $p->{days}, 'local datetime: days';
375 1         351 is $dt->epoch, -1, 'local datetime: epoch';
376 1         352 is $dt->nanoseconds, 0, 'local datetime: nanoseconds';
377 1         356 is $dt->seconds, $p->{seconds}, 'local datetime: seconds';
378 1         353 is $dt->type, $type, 'local datetime: type';
379 1         360 is $dt->tz_name, $p->{tz_name}, 'local datetime: no tz_name';
380 1         417 is $dt->tz_offset, $p->{tz_offset}, 'local datetime: no tz_offset';
381            
382 1         428 $type = 'ZONED DATETIME';
383 1         6 $dt = $new->($datetime_class, $p = {
384             days => 7252, # 1989-11-09
385             seconds => 61043, # 17:57:23 UTC
386             nanoseconds => 0,
387             tz_offset => 5400, # +1.5 h
388             });
389 1         9 is $dt->days, $p->{days}, 'zoned datetime (offset): days';
390 1         363 is $dt->epoch, 626633843, 'zoned datetime (offset): epoch';
391 1         351 is $dt->nanoseconds, $p->{nanoseconds}, 'zoned datetime (offset): nanoseconds';
392 1         350 is $dt->seconds, $p->{seconds}, 'zoned datetime (offset): seconds';
393 1         374 is $dt->type, $type, 'zoned datetime (offset): type';
394 1         360 is $dt->tz_name, undef, 'zoned datetime (half hour offset): no tz_name';
395 1         416 is $dt->tz_offset, $p->{tz_offset}, 'zoned datetime (offset): tz_offset';
396            
397 1         365 $dt = $new->($datetime_class, $p = {
398             days => 6560, # 1987-12-18
399             seconds => 72000, # 20:00 UTC
400             nanoseconds => 0,
401             tz_name => 'America/Los_Angeles',
402             });
403 1         9 is $dt->days, $p->{days}, 'zoned datetime: days';
404 1         352 is $dt->epoch, 566856000, 'zoned datetime: epoch';
405 1         356 is $dt->nanoseconds, $p->{nanoseconds}, 'zoned datetime: nanoseconds';
406 1         360 is $dt->seconds, $p->{seconds}, 'zoned datetime: seconds';
407 1         394 is $dt->type, $type, 'zoned datetime: type';
408 1         360 is $dt->tz_name, $p->{tz_name}, 'zoned datetime: tz_name';
409 1         374 is $dt->tz_offset, $p->{tz_offset}, 'zoned datetime: no tz_offset';
410            
411 1         435 $dt = $new->($datetime_class, $p = {
412             days => 0,
413             seconds => 0,
414             tz_offset => 0, # GMT
415             });
416 1         10 is $dt->days, 0, 'zoned datetime (zero offset): days';
417 1         361 is $dt->epoch, 0, 'zoned datetime (zero offset): epoch';
418 1         353 is $dt->nanoseconds, 0, 'zoned datetime (zero offset): nanoseconds';
419 1         353 is $dt->seconds, 0, 'zoned datetime (zero offset): seconds';
420 1         391 is $dt->type, $type, 'zoned datetime (zero offset): type';
421 1         373 is $dt->tz_name, 'Etc/GMT', 'zoned datetime (zero offset): tz_name';
422 1         381 is $dt->tz_offset, 0, 'zoned datetime (zero offset): tz_offset';
423            
424 1         375 $dt = $new->($datetime_class, $p = {
425             days => 0,
426             seconds => 0,
427             tz_offset => 86400, # Zone Etc/GMT-24 doesn't exist
428             });
429 1         9 is $dt->days, 0, 'zoned datetime (large offset): days';
430 1         353 is $dt->epoch, 0, 'zoned datetime (large offset): epoch';
431 1         355 is $dt->nanoseconds, 0, 'zoned datetime (large offset): nanoseconds';
432 1         359 is $dt->seconds, 0, 'zoned datetime (large offset): seconds';
433 1         356 is $dt->type, $type, 'zoned datetime (large offset): type';
434 1         361 is $dt->tz_name, undef, 'zoned datetime (large offset): no tz_name';
435 1         434 is $dt->tz_offset, 86400, 'zoned datetime (large offset): tz_offset';
436            
437 1         358 ok $dt->DOES('Neo4j::Types::DateTime'), 'does role';
438             }
439              
440              
441             sub neo4j_datetime_ok {
442 1     1 1 1326 my ($class, $new, $name) = @_;
443 1   33     9 $name //= "neo4j_datetime_ok '$class'";
444 1     1   7 subtest $name, sub { _datetime_test($class, $new) };
  1         718  
445             }
446              
447              
448             sub _duration_test {
449 1     1   2 my ($duration_class, $new) = @_;
450            
451 1         4 plan tests => 2 * 4 + 1;
452            
453 1         552 my $d;
454            
455 1         6 $d = $new->($duration_class, {
456             months => 18,
457             seconds => 172800,
458             });
459 1         14 is $d->months, 18, 'months';
460 1         379 is $d->days, 0, 'no days yields zero';
461 1         355 is $d->seconds, 172800, 'seconds';
462 1         359 is $d->nanoseconds, 0, 'no nanoseconds yields zero';
463            
464 1         354 $d = $new->($duration_class, {
465             days => -42,
466             nanoseconds => -2000,
467             });
468 1         14 is $d->months, 0, 'no months yields zero';
469 1         352 is $d->days, -42, 'days';
470 1         356 is $d->seconds, 0, 'no seconds yields zero';
471 1         352 is $d->nanoseconds, -2000, 'nanoseconds';
472            
473 1         371 ok $d->DOES('Neo4j::Types::Duration'), 'does role';
474             }
475              
476              
477             sub neo4j_duration_ok {
478 1     1 1 1357 my ($class, $new, $name) = @_;
479 1   33     10 $name //= "neo4j_duration_ok '$class'";
480 1     1   6 subtest $name, sub { _duration_test($class, $new) };
  1         768  
481             }
482              
483              
484             package # private
485             Test::Neo4j::Types::PathNode;
486 12     12   59 sub DOES { $_[1] eq 'Neo4j::Types::Node' }
487              
488              
489             package # private
490             Test::Neo4j::Types::PathRel;
491 6     6   18 sub DOES { $_[1] eq 'Neo4j::Types::Relationship' }
492              
493              
494             1;