< Summary

Information
Class: ShopGuard.Core.Configuration.SettingsLoader
Assembly: ShopGuard.Core
File(s): /home/runner/work/ShopGuard/ShopGuard/ShopGuard/ShopGuard.Core/Configuration/SettingsLoader.cs
Line coverage
100%
Covered lines: 26
Uncovered lines: 0
Coverable lines: 26
Total lines: 60
Line coverage: 100%
Branch coverage
81%
Covered branches: 18
Total branches: 22
Branch coverage: 81.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Load(...)81.81%2222100%

File(s)

/home/runner/work/ShopGuard/ShopGuard/ShopGuard/ShopGuard.Core/Configuration/SettingsLoader.cs

#LineLine coverage
 1using Microsoft.Extensions.Configuration;
 2
 3namespace ShopGuard.Core.Configuration;
 4
 5/// <summary>
 6/// Loads <see cref="TestSettings"/> from a JSON file and environment variables.
 7/// Precedence (highest wins): SHOPGUARD_* env vars > environment section > root section.
 8/// </summary>
 9public static class SettingsLoader
 10{
 11    public const string EnvVarPrefix = "SHOPGUARD_";
 12
 13    /// <summary>
 14    /// Loads settings for the given environment (e.g. "local", "staging").
 15    /// The JSON file contains a root "TestSettings" section plus optional
 16    /// per-environment override sections ("Environments:{name}").
 17    /// </summary>
 18    public static TestSettings Load(string jsonPath, string environment = "local")
 19    {
 520        if (!File.Exists(jsonPath))
 21        {
 122            throw new FileNotFoundException($"Test configuration not found: {jsonPath}", jsonPath);
 23        }
 24
 425        var configuration = new ConfigurationBuilder()
 426            .AddJsonFile(jsonPath, optional: false)
 427            .AddEnvironmentVariables(EnvVarPrefix)
 428            .Build();
 29
 430        var settings = configuration.GetSection("TestSettings").Get<TestSettings>()
 431            ?? throw new InvalidOperationException("Section 'TestSettings' is missing or invalid.");
 32
 33        // Apply per-environment overrides on top of the defaults.
 434        var overrides = configuration.GetSection($"Environments:{environment}");
 435        if (overrides.Exists())
 36        {
 137            settings = new TestSettings
 138            {
 139                ShopBaseUrl = overrides["ShopBaseUrl"] ?? settings.ShopBaseUrl,
 140                ApiBaseUrl = overrides["ApiBaseUrl"] ?? settings.ApiBaseUrl,
 141                ApiUsername = overrides["ApiUsername"] ?? settings.ApiUsername,
 142                ApiPassword = overrides["ApiPassword"] ?? settings.ApiPassword,
 143                DbConnectionString = overrides["DbConnectionString"] ?? settings.DbConnectionString,
 144                Headless = bool.TryParse(overrides["Headless"], out var headless) ? headless : settings.Headless,
 145                DefaultTimeoutMs = int.TryParse(overrides["DefaultTimeoutMs"], out var timeout)
 146                    ? timeout
 147                    : settings.DefaultTimeoutMs,
 148            };
 49        }
 50
 51        // HEADLESS=false (CI convenience variable) wins over everything else.
 452        var headlessEnv = Environment.GetEnvironmentVariable("HEADLESS");
 453        if (bool.TryParse(headlessEnv, out var headlessOverride))
 54        {
 155            settings = settings with { Headless = headlessOverride };
 56        }
 57
 458        return settings;
 59    }
 60}