1use strict; 2use warnings; 3use Test::More; 4use Test::Fatal; 5use Carp 'croak'; 6 7use Dancer2::Core::Runner; 8use Dancer2::FileUtils qw/dirname path/; 9use File::Spec; 10use File::Temp; 11 12# undefine ENV vars used as defaults for app environment in these tests 13local $ENV{DANCER_ENVIRONMENT}; 14local $ENV{PLACK_ENV}; 15 16my $runner = Dancer2::Core::Runner->new(); 17my $location = File::Spec->rel2abs( path( dirname(__FILE__), 'config' ) ); 18my $location2 = File::Spec->rel2abs( path( dirname(__FILE__), 'config2' ) ); 19 20{ 21 22 package Prod; 23 use Moo; 24 with 'Dancer2::Core::Role::ConfigReader'; 25 26 sub name {'Prod'} 27 28 sub _build_environment {'production'} 29 sub _build_location {$location} 30 sub _build_default_config {$runner->config} 31 32 package Dev; 33 use Moo; 34 with 'Dancer2::Core::Role::ConfigReader'; 35 36 sub _build_environment {'development'} 37 sub _build_location {$location}; 38 sub _build_default_config {$runner->config} 39 40 package Failure; 41 use Moo; 42 with 'Dancer2::Core::Role::ConfigReader'; 43 44 sub _build_environment {'failure'} 45 sub _build_location {$location} 46 sub _build_default_config {$runner->config} 47 48 package Staging; 49 use Moo; 50 with 'Dancer2::Core::Role::ConfigReader'; 51 52 sub _build_environment {'staging'} 53 sub _build_location {$location} 54 sub _build_default_config {$runner->config} 55 56 package Merging; 57 use Moo; 58 with 'Dancer2::Core::Role::ConfigReader'; 59 60 sub name {'Merging'} 61 62 sub _build_environment {'merging'} 63 sub _build_location {$location} 64 sub _build_default_config {$runner->config} 65 66 package LocalConfig; 67 use Moo; 68 with 'Dancer2::Core::Role::ConfigReader'; 69 70 sub name {'LocalConfig'} 71 72 sub _build_environment {'lconfig'} 73 sub _build_location {$location2} 74 sub _build_default_config {$runner->config} 75 76} 77 78my $d = Dev->new(); 79is_deeply $d->config_files, 80 [ path( $location, 'config.yml' ), ], 81 "config_files() only sees existing files"; 82 83my $f = Prod->new; 84is $f->does('Dancer2::Core::Role::ConfigReader'), 1, 85 "role Dancer2::Core::Role::ConfigReader is consumed"; 86 87is_deeply $f->config_files, 88 [ path( $location, 'config.yml' ), 89 path( $location, 'environments', 'production.yml' ), 90 ], 91 "config_files() works"; 92 93my $j = Staging->new; 94is_deeply $j->config_files, 95 [ path( $location, 'config.yml' ), 96 path( $location, 'environments', 'staging.json' ), 97 ], 98 "config_files() does JSON too!"; 99 100note "bad YAML file"; 101my $fail = Failure->new; 102is $fail->environment, 'failure'; 103 104is_deeply $fail->config_files, 105 [ path( $location, 'config.yml' ), 106 path( $location, 'environments', 'failure.yml' ), 107 ], 108 "config_files() works"; 109 110like( 111 exception { $fail->config }, 112 qr{Unable to parse the configuration file}, 'Configuration file parsing failure', 113); 114 115note "config merging"; 116my $m = Merging->new; 117 118# Check the 'application' top-level key; its the only key that 119# is currently a HoH in the test configurations 120is_deeply $m->config->{application}, 121 { some_feature => 'bar', 122 another_setting => 'baz', 123 }, 124 "full merging of configuration hashes"; 125 126{ 127 my $l = LocalConfig->new; 128 129 is_deeply $l->config_files, 130 [ path( $location2, 'config.yml' ), 131 path( $location2, 'config_local.yml' ), 132 path( $location2, 'environments', 'lconfig.yml' ), 133 path( $location2, 'environments', 'lconfig_local.yml' ), 134 ], 135 "config_files() with local config works"; 136 137 is_deeply $l->config->{application}, 138 { feature_1 => 'foo', 139 feature_2 => 'alpha', 140 feature_3 => 'replacement', 141 feature_4 => 'blat', 142 feature_5 => 'beta', 143 feature_6 => 'bar', 144 feature_7 => 'baz', 145 feature_8 => 'goober', 146 }, 147 "full merging of local configuration hashes"; 148 149} 150 151note "config parsing"; 152 153is $f->config->{show_errors}, 0; 154is $f->config->{main}, 1; 155is $f->config->{charset}, 'utf-8', "normalized UTF-8 to utf-8"; 156 157ok( $f->has_setting('charset') ); 158ok( !$f->has_setting('foobarbaz') ); 159 160note "default values"; 161is $f->setting('apphandler'), 'Standalone'; 162 163like( 164 exception { $f->_normalize_config( { charset => 'BOGUS' } ) }, 165 qr{Charset defined in configuration is wrong : couldn't identify 'BOGUS'}, 166 'Configuration file charset failure', 167); 168 169{ 170 171 package Foo; 172 use Carp 'croak'; 173 sub foo { croak "foo" } 174} 175 176is $f->setting('traces'), 0; 177unlike( exception { Foo->foo() }, qr{Foo::foo}, "traces are not enabled", ); 178 179$f->setting( traces => 1 ); 180like( exception { Foo->foo() }, qr{Foo::foo}, "traces are enabled", ); 181 182{ 183 my $tmpdir = File::Temp::tempdir( CLEANUP => 1, TMPDIR => 1 ); 184 $ENV{DANCER_CONFDIR} = $tmpdir; 185 my $f = Prod->new; 186 is $f->config_location, $tmpdir; 187} 188 189done_testing; 190