Config-Abstraction

 view release on metacpan or  search on metacpan

t/integration.t  view on Meta::CPAN

	# Keys not in file retain data defaults
	is($cfg->get('retries'), $EXPECTED_RETRIES, 'data default retained for key absent from YAML');

	# config_path records the file
	my $all = $cfg->all();
	my @paths = @{$all->{config_path}};
	ok(grep { /\Q$YAML_BASE\E/ } @paths, 'config_path includes YAML file');
};

# ===========================================================================
# File loading end-to-end: local overrides base
# ===========================================================================
subtest 'end-to-end: local.yaml overrides base.yaml' => sub {
	my $dir = tempdir(CLEANUP => 1);
	_write_file($dir, $YAML_BASE,  "level: base\ntimeout: $EXPECTED_TIMEOUT\n");
	_write_file($dir, $YAML_LOCAL, "level: local\n");

	my $cfg = new_ok($MODULE => [config_dirs => [$dir]]);

	is($cfg->get('level'),   'local',            'local.yaml overrides base.yaml');
	is($cfg->get('timeout'), $EXPECTED_TIMEOUT,  'base.yaml value retained when not in local');
};

# ===========================================================================
# File loading end-to-end: JSON
# ===========================================================================
subtest 'end-to-end: JSON file loaded and accessible' => sub {
	my $dir = tempdir(CLEANUP => 1);
	_write_file($dir, $JSON_BASE,
		qq({"database":{"user":"$OVERRIDE_USER","port":$OVERRIDE_PORT},"retries":$EXPECTED_RETRIES}));

	my $cfg = new_ok($MODULE => [config_dirs => [$dir]]);

	is($cfg->get('database.user'), $OVERRIDE_USER, 'JSON database.user loaded');
	is($cfg->get('database.port'), $OVERRIDE_PORT, 'JSON database.port loaded');
	is($cfg->get('retries'),       $EXPECTED_RETRIES, 'JSON retries loaded');
};

# ===========================================================================
# File loading end-to-end: INI
# ===========================================================================
subtest 'end-to-end: INI file loaded and accessible' => sub {
	my $dir = tempdir(CLEANUP => 1);
	_write_file($dir, $INI_BASE, <<END);
[database]
user=$OVERRIDE_USER
port=$OVERRIDE_PORT
END

	my $cfg = new_ok($MODULE => [config_dirs => [$dir]]);

	is($cfg->get('database.user'), $OVERRIDE_USER, 'INI database.user loaded');
	is($cfg->get('database.port'), $OVERRIDE_PORT, 'INI database.port loaded');
};

# ===========================================================================
# Full merge precedence stack: data < file < ENV < CLI
# ===========================================================================
subtest 'end-to-end: full merge precedence stack' => sub {
	local %ENV = %ENV;
	local @ARGV = ("--${ENV_PREFIX}DATABASE__USER=cli_user");
	$ENV{"${ENV_PREFIX}DATABASE__PORT"} = $OVERRIDE_PORT;

	my $dir = tempdir(CLEANUP => 1);
	_write_file($dir, $YAML_BASE,
		"database:\n  user: file_user\n  port: $EXPECTED_PORT\n  host: $EXPECTED_HOST\n");

	my $cfg = new_ok($MODULE => [
		data        => _fresh_data(),
		config_dirs => [$dir],
		env_prefix  => $ENV_PREFIX,
	]);

	# CLI beats everything
	is($cfg->get('database.user'), 'cli_user',    'CLI wins over ENV/file/data');
	# ENV beats file and data
	is($cfg->get('database.port'), $OVERRIDE_PORT, 'ENV wins over file/data');
	# File beats data
	is($cfg->get('database.host'), $EXPECTED_HOST, 'file value present');
	# Data provides fallback
	is($cfg->get('retries'), $EXPECTED_RETRIES,   'data fallback intact');
};

# ===========================================================================
# merge_defaults() integration with caller package workflow
# POD: merge_defaults is designed for use in other modules' new() methods
# ===========================================================================
subtest 'end-to-end: merge_defaults() workflow as documented in POD' => sub {
	my $cfg = new_ok($MODULE => [
		data        => _fresh_data(),
		config_dirs => [],
	]);

	# Simulate the documented pattern: caller passes its own $params hash
	my $caller_params = {
		timeout => 99,
		retries => 99,
		extra   => 'caller_value',
	};

	my $merged = $cfg->merge_defaults(
		defaults => $caller_params,
		merge    => 1,
	);

	# Config overrides caller defaults on conflict
	is($merged->{retries}, $EXPECTED_RETRIES, 'config wins over caller default');
	is($merged->{timeout}, $EXPECTED_TIMEOUT, 'config wins over caller timeout');

	# Caller-only keys preserved
	is($merged->{extra}, 'caller_value', 'caller-only key preserved');
};

subtest 'end-to-end: merge_defaults() with global section' => sub {
	my $cfg = new_ok($MODULE => [
		data => {
			global  => { timeout => $GLOBAL_TIMEOUT, loglevel => $EXPECTED_LEVEL },
			retries => $EXPECTED_RETRIES,
		},
		config_dirs => [],
	]);



( run in 0.540 second using v1.01-cache-2.11-cpan-9169edd2b0e )