1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Test::More tests => 37;
7use Test::Exception;
8
9BEGIN { 
10	use_ok('Tree::Simple::Visitor'); 	
11};
12
13use Tree::Simple;
14
15my $SIMPLE_SUB = sub { "test sub" };
16# execute this otherwise Devel::Cover gives odd stats
17$SIMPLE_SUB->();
18
19# check that we have a constructor
20can_ok("Tree::Simple::Visitor", 'new');
21
22# -----------------------------------------------
23# test the new style interface
24# -----------------------------------------------
25
26my $visitor = Tree::Simple::Visitor->new();
27isa_ok($visitor, 'Tree::Simple::Visitor');
28
29my $tree = Tree::Simple->new(Tree::Simple->ROOT)
30					   ->addChildren(
31							Tree::Simple->new("1")
32                                        ->addChildren(
33                                            Tree::Simple->new("1.1"),
34                                            Tree::Simple->new("1.2")
35                                                        ->addChild(Tree::Simple->new("1.2.1")),
36                                            Tree::Simple->new("1.3")                                            
37                                        ),
38							Tree::Simple->new("2"),
39							Tree::Simple->new("3"),							
40					   );
41isa_ok($tree, 'Tree::Simple');
42
43$tree->accept($visitor);
44
45can_ok($visitor, 'getResults');
46is_deeply(
47        [ $visitor->getResults() ],
48        [ qw(1 1.1 1.2 1.2.1 1.3 2 3)],
49        '... got what we expected');
50
51can_ok($visitor, 'setNodeFilter');
52
53my $node_filter = sub { return "_" . $_[0]->getNodeValue() };
54$visitor->setNodeFilter($node_filter);
55
56can_ok($visitor, 'getNodeFilter');
57is($visitor->getNodeFilter(), "$node_filter", '... got back what we put in');
58
59# visit the tree again to get new results now
60$tree->accept($visitor);
61
62is_deeply(
63        scalar $visitor->getResults(),
64        [ qw(_1 _1.1 _1.2 _1.2.1 _1.3 _2 _3)],
65        '... got what we expected');
66        
67# test some exceptions
68
69throws_ok {
70    $visitor->setNodeFilter();        
71} qr/Insufficient Arguments/, '... this should die';
72
73throws_ok {
74    $visitor->setNodeFilter([]);        
75} qr/Insufficient Arguments/, '... this should die';
76
77# -----------------------------------------------
78# test the old style interface for backwards 
79# compatability
80# -----------------------------------------------
81
82# and that our RECURSIVE constant is properly defined
83can_ok("Tree::Simple::Visitor", 'RECURSIVE');
84# and that our CHILDREN_ONLY constant is properly defined
85can_ok("Tree::Simple::Visitor", 'CHILDREN_ONLY');
86
87# no depth
88my $visitor1 = Tree::Simple::Visitor->new($SIMPLE_SUB);
89isa_ok($visitor1, 'Tree::Simple::Visitor');
90
91# children only
92my $visitor2 = Tree::Simple::Visitor->new($SIMPLE_SUB, Tree::Simple::Visitor->CHILDREN_ONLY);
93isa_ok($visitor2, 'Tree::Simple::Visitor');
94
95# recursive
96my $visitor3 = Tree::Simple::Visitor->new($SIMPLE_SUB, Tree::Simple::Visitor->RECURSIVE);
97isa_ok($visitor3, 'Tree::Simple::Visitor');
98
99# -----------------------------------------------
100# test constructor exceptions
101# -----------------------------------------------
102
103# we pass a bad depth (string)
104throws_ok {
105	my $test = Tree::Simple::Visitor->new($SIMPLE_SUB, "Fail")
106} qr/Insufficient Arguments \: Depth arguement must be either RECURSIVE or CHILDREN_ONLY/, 
107   '... we are expecting this error';
108   
109# we pass a bad depth (numeric)
110throws_ok {
111	my $test = Tree::Simple::Visitor->new($SIMPLE_SUB, 100)
112} qr/Insufficient Arguments \: Depth arguement must be either RECURSIVE or CHILDREN_ONLY/, 
113   '... we are expecting this error';     
114
115# we pass a non-ref func argument
116throws_ok {
117	my $test = Tree::Simple::Visitor->new("Fail");
118} qr/Insufficient Arguments \: filter function argument must be a subroutine reference/,
119   '... we are expecting this error';
120
121# we pass a non-code-ref func arguement   
122throws_ok {
123	my $test = Tree::Simple::Visitor->new([]);
124} qr/Insufficient Arguments \: filter function argument must be a subroutine reference/,
125   '... we are expecting this error';   
126
127# -----------------------------------------------
128# test other exceptions
129# -----------------------------------------------
130
131# and make sure we can call the visit method
132can_ok($visitor1, 'visit');
133
134# test no arg
135throws_ok {
136	$visitor1->visit();
137} qr/Insufficient Arguments \: You must supply a valid Tree\:\:Simple object/,
138   '... we are expecting this error'; 
139   
140# test non-ref arg
141throws_ok {
142	$visitor1->visit("Fail");
143} qr/Insufficient Arguments \: You must supply a valid Tree\:\:Simple object/,
144   '... we are expecting this error'; 	 
145   
146# test non-object ref arg
147throws_ok {
148	$visitor1->visit([]);
149} qr/Insufficient Arguments \: You must supply a valid Tree\:\:Simple object/,
150   '... we are expecting this error'; 	   
151   
152my $BAD_OBJECT = bless({}, "Test");   
153   
154# test non-Tree::Simple object arg
155throws_ok {
156	$visitor1->visit($BAD_OBJECT);
157} qr/Insufficient Arguments \: You must supply a valid Tree\:\:Simple object/,
158   '... we are expecting this error'; 	   
159   
160
161# -----------------------------------------------
162# Test accept & visit
163# -----------------------------------------------
164# Note: 
165# this test could be made more robust by actually
166# getting results and testing them from the 
167# Visitor object. But for right now it is good
168# enough to have the code coverage, and know
169# all the peices work.
170# -----------------------------------------------
171
172# now make a tree
173my $tree1 = Tree::Simple->new(Tree::Simple->ROOT)
174					   ->addChildren(
175							Tree::Simple->new("1.0"),
176							Tree::Simple->new("2.0"),
177							Tree::Simple->new("3.0"),							
178					   );
179isa_ok($tree1, 'Tree::Simple');
180
181cmp_ok($tree1->getChildCount(), '==', 3, '... there are 3 children here');
182
183# and pass the visitor1 to accept
184lives_ok {
185	$tree1->accept($visitor1);
186} '.. this passes fine';
187
188# and pass the visitor2 to accept
189lives_ok {
190	$tree1->accept($visitor2);
191} '.. this passes fine';
192
193# and pass the visitor3 to accept
194lives_ok {
195	$tree1->accept($visitor3);
196} '.. this passes fine';
197
198# ----------------------------------------------------
199# test some misc. weirdness to get the coverage up :P
200# ----------------------------------------------------
201
202# check that includeTrunk works as we expect it to
203{
204    my $visitor = Tree::Simple::Visitor->new();
205    ok(!$visitor->includeTrunk(), '... this should be false right now');
206
207    $visitor->includeTrunk("true");
208    ok($visitor->includeTrunk(), '... this should be true now');
209    
210    $visitor->includeTrunk(undef);
211    ok($visitor->includeTrunk(), '... this should be true still');
212    
213    $visitor->includeTrunk("");
214    ok(!$visitor->includeTrunk(), '... this should be false again');
215}
216
217# check that clearNodeFilter works as we expect it to
218{
219    my $visitor = Tree::Simple::Visitor->new();
220    
221    my $filter = sub { "filter" };
222    
223    $visitor->setNodeFilter($filter);
224    is($visitor->getNodeFilter(), $filter, 'our node filter is set correctly');
225    
226    $visitor->clearNodeFilter();
227    ok(! defined($visitor->getNodeFilter()), '... our node filter has now been undefined'); 
228}
229
230
231