3e420ac610b7c0c6997b75f4a3fbd96b95012eb6
[gitmo/MooseX-Getopt.git] / t / 008_configfromfile.t
1 use strict;
2 use warnings;
3
4 use Test::Requires { 'MooseX::ConfigFromFile' => '0.06' };    # skip all if not installed
5 use Test::More tests => 56;
6 use Test::Fatal;
7 use Test::Deep '!blessed';
8 use Path::Tiny;
9 use Scalar::Util 'blessed';
10 use Test::NoWarnings 1.04 ':early';
11
12 my %constructor_args;
13 {
14     package App;
15
16     use Moose;
17     with 'MooseX::Getopt';
18     with 'MooseX::ConfigFromFile';
19
20     has 'config_from_override' => (
21         is       => 'ro',
22         isa      => 'Bool',
23         default  => 0,
24     );
25
26     has 'optional_from_config' => (
27         is        => 'ro',
28         isa       => 'Str',
29         required  => 0,
30     );
31
32     has 'required_from_config' => (
33         is        => 'ro',
34         isa       => 'Str',
35         required  => 1,
36     );
37
38     has 'required_from_argv' => (
39         is        => 'ro',
40         isa       => 'Str',
41         required  => 1,
42     );
43
44     sub get_config_from_file
45     {
46         my ( $class, $file ) = @_;
47
48         my %config = (
49             required_from_config => 'from_config_1',
50             optional_from_config => 'from_config_2',
51         );
52
53         if ( $file ne Path::Tiny::path('/notused/default') ) {
54             $config{config_from_override} = 1;
55         }
56
57         return \%config;
58     }
59
60     around BUILDARGS => sub
61     {
62         my ($orig, $class) = (shift, shift);
63         my $args = $class->$orig(@_);
64         $constructor_args{$class} = $args;
65     };
66 }
67
68 {
69     package App::DefaultConfigFile;
70
71     use Moose;
72     extends 'App';
73
74     has '+configfile' => (
75         default => Path::Tiny::path('/notused/default')->stringify,
76     );
77 }
78
79 {
80     package App::DefaultConfigFileCodeRef;
81
82     use Moose;
83     extends 'App';
84
85     has '+configfile' => (
86         default => sub { return Path::Tiny::path('/notused/default') },
87     );
88 }
89
90 {
91     package App::ConfigFileWrapped;
92
93     use Moose;
94     extends 'App';
95
96     around configfile => sub { '/notused/default' };
97 }
98
99
100 # No config specified
101 {
102     local @ARGV = qw( --required_from_argv 1 );
103
104     like exception { App->new_with_options },
105         ($Getopt::Long::Descriptive::VERSION >= 0.091
106             ? qr/Mandatory parameter 'required_from_config' missing/
107             : qr/Required option missing: required_from_config/);
108
109     {
110         my $app = App::DefaultConfigFile->new_with_options;
111         isa_ok( $app, 'App::DefaultConfigFile' );
112         app_ok( $app );
113
114         ok(  !$app->config_from_override,
115             '... config_from_override false as expected' );
116
117         is( $app->configfile, path('/notused/default'),
118             '... configfile is /notused/default as expected' );
119
120         cmp_deeply(
121             $constructor_args{blessed($app)},
122             superhashof({
123                 configfile => str(path('/notused/default')),
124             }),
125             'correct constructor args passed',
126         );
127     }
128
129     {
130         my $app = App::DefaultConfigFileCodeRef->new_with_options;
131         isa_ok( $app, 'App::DefaultConfigFileCodeRef' );
132         app_ok( $app );
133
134         ok(  !$app->config_from_override,
135             '... config_from_override false as expected' );
136
137         is( $app->configfile, path('/notused/default'),
138             '... configfile is /notused/default as expected' );
139
140         cmp_deeply(
141             $constructor_args{blessed $app},
142             superhashof({
143                 configfile => str(path('/notused/default')),
144             }),
145             'correct constructor args passed',
146         );
147     }
148
149     {
150         my $app = App::ConfigFileWrapped->new_with_options;
151         isa_ok( $app, 'App::ConfigFileWrapped' );
152         app_ok( $app );
153
154         ok(  !$app->config_from_override,
155             '... config_from_override false as expected' );
156
157         is( $app->configfile, path('/notused/default'),
158             '... configfile is /notused/default as expected' );
159
160         cmp_deeply(
161             $constructor_args{blessed $app},
162             superhashof({
163                 configfile => str(path('/notused/default')),
164             }),
165             'correct constructor args passed',
166         );
167     }
168 }
169
170 # Config specified
171 {
172     local @ARGV = qw( --configfile /notused/override --required_from_argv 1 );
173
174     {
175         my $app = App->new_with_options;
176         isa_ok( $app, 'App' );
177         app_ok( $app );
178     }
179
180     {
181         my $app = App::DefaultConfigFile->new_with_options;
182         isa_ok( $app, 'App::DefaultConfigFile' );
183         app_ok( $app );
184
185         ok( $app->config_from_override,
186              '... config_from_override true as expected' );
187
188         is( $app->configfile, path('/notused/override'),
189             '... configfile is /notused/override as expected' );
190
191         cmp_deeply(
192             $constructor_args{blessed $app},
193             superhashof({
194                 configfile => str(path('/notused/override')),
195             }),
196             'correct constructor args passed',
197         );
198     }
199     {
200         my $app = App::DefaultConfigFileCodeRef->new_with_options;
201         isa_ok( $app, 'App::DefaultConfigFileCodeRef' );
202         app_ok( $app );
203
204         ok( $app->config_from_override,
205              '... config_from_override true as expected' );
206
207         is( $app->configfile, path('/notused/override'),
208             '... configfile is /notused/override as expected' );
209
210         cmp_deeply(
211             $constructor_args{blessed $app},
212             superhashof({
213                 configfile => str(path('/notused/override')),
214             }),
215             'correct constructor args passed',
216         );
217     }
218     TODO: {
219         my $app = App::ConfigFileWrapped->new_with_options;
220         isa_ok( $app, 'App::ConfigFileWrapped' );
221         app_ok( $app );
222
223         ok( $app->config_from_override,
224              '... config_from_override true as expected' );
225
226 # FIXME - in order for this to work, we need to fix CFF so the
227 # configfile method always returns the actual value of the attribute,
228 # not the default sub thingy.
229         local $TODO = 'MooseX::ConfigFromFile needs fixes';
230         is( $app->configfile, path('/notused/override'),
231             '... configfile is /notused as expected' );
232
233         cmp_deeply(
234             $constructor_args{blessed $app},
235             superhashof({
236                 configfile => str(path('/notused/override')),
237             }),
238             'correct constructor args passed',
239         );
240     }
241 }
242
243 # Required arg not supplied from cmdline
244 {
245     local @ARGV = qw( --configfile /notused/override );
246     like exception { App->new_with_options },
247         ($Getopt::Long::Descriptive::VERSION >= 0.091
248             ? qr/Mandatory parameter 'required_from_argv' missing/
249             : qr/Required option missing: required_from_argv/);
250 }
251
252 # Config file value overriden from cmdline
253 {
254     local @ARGV = qw( --configfile /notused/override --required_from_argv 1 --required_from_config override );
255
256     my $app = App->new_with_options;
257     isa_ok( $app, 'App' );
258
259     is( $app->required_from_config, 'override',
260         '... required_from_config is override as expected' );
261
262     is( $app->optional_from_config, 'from_config_2',
263         '... optional_from_config is from_config_2 as expected' );
264 }
265
266 # No config file
267 {
268     local @ARGV = qw( --required_from_argv 1 --required_from_config noconfig );
269
270     my $app = App->new_with_options;
271     isa_ok( $app, 'App' );
272
273     is( $app->required_from_config, 'noconfig',
274         '... required_from_config is noconfig as expected' );
275
276     ok( !defined $app->optional_from_config,
277         '... optional_from_config is undef as expected' );
278 }
279
280 {
281     package BaseApp::WithConfig;
282     use Moose;
283     with 'MooseX::ConfigFromFile';
284
285     sub get_config_from_file { return {}; }
286 }
287
288 {
289     package DerivedApp::Getopt;
290     use Moose;
291     extends 'BaseApp::WithConfig';
292     with 'MooseX::Getopt';
293 }
294
295 # With DerivedApp, the Getopt role was applied at a different level
296 # than the ConfigFromFile role
297 {
298     ok ! exception { DerivedApp::Getopt->new_with_options }, 'Can create DerivedApp';
299 }
300
301 sub app_ok {
302     my $app = shift;
303
304     is( $app->required_from_config, 'from_config_1',
305         '... required_from_config is from_config_1 as expected' );
306
307     is( $app->optional_from_config, 'from_config_2',
308         '... optional_from_config is from_config_2 as expected' );
309
310     is( $app->required_from_argv, '1',
311         '... required_from_argv is 1 as expected' );
312 }