@@ -324,6 +324,138 @@ func TestFromYAMLFile(t *testing.T) {
324324 })
325325}
326326
327+ // testFlags is a struct that implements the Flags interface.
328+ // It holds information about the configuration file path and whether it was explicitly set.
329+ type testFlags struct {
330+ configPath string // The path to the configuration file.
331+ explicitConfigPath bool // Indicates if the config path was explicitly set.
332+ }
333+
334+ // GetConfigPath returns the path to the configuration file.
335+ func (f testFlags ) GetConfigPath () string {
336+ return f .configPath
337+ }
338+
339+ // IsExplicitConfigPath indicates whether the configuration file path was explicitly set.
340+ func (f testFlags ) IsExplicitConfigPath () bool {
341+ return f .explicitConfigPath
342+ }
343+
344+ func TestLoad (t * testing.T ) {
345+ loadTests := []testutils.TestCase [Validator , testutils.ConfigTestData ]{
346+ {
347+ Name : "Load from YAML only" ,
348+ Data : testutils.ConfigTestData {
349+ Yaml : `key: value` ,
350+ },
351+ Expected : & simpleConfig {
352+ Key : "value" ,
353+ },
354+ },
355+ {
356+ Name : "Load from Env only" ,
357+ Data : testutils.ConfigTestData {
358+ Env : map [string ]string {"KEY" : "value" },
359+ },
360+ Expected : & simpleConfig {
361+ Key : "value" ,
362+ },
363+ },
364+ {
365+ Name : "YAML and Env; Env overrides" ,
366+ Data : testutils.ConfigTestData {
367+ Yaml : `key: yaml-value` ,
368+ Env : map [string ]string {"KEY" : "env-value" },
369+ },
370+ Expected : & simpleConfig {
371+ Key : "env-value" ,
372+ },
373+ },
374+ {
375+ Name : "YAML and Env; Env overrides defaults" ,
376+ Data : testutils.ConfigTestData {
377+ Yaml : `key: yaml-value` ,
378+ Env : map [string ]string {
379+ "DEFAULT_KEY" : "env-value" ,
380+ }},
381+ Expected : & defaultConfig {
382+ Key : "yaml-value" ,
383+ Default : defaultConfigPart {Key : "env-value" },
384+ },
385+ },
386+ {
387+ Name : "YAML and Env; Env supplements" ,
388+ Data : testutils.ConfigTestData {
389+ Yaml : `key: yaml-value` ,
390+ Env : map [string ]string {"EMBEDDED_EMBEDDED_KEY" : "env-value" }},
391+ Expected : & embeddedConfig {
392+ Key : "yaml-value" ,
393+ Embedded : embeddedConfigPart {Key : "env-value" },
394+ },
395+ },
396+ {
397+ Name : "Validate invalid" ,
398+ Data : testutils.ConfigTestData {
399+ Yaml : `key: value` ,
400+ Env : map [string ]string {"KEY" : "value" },
401+ },
402+ Expected : & invalidConfig {
403+ Key : "value" ,
404+ },
405+ Error : testutils .ErrorIs (errInvalidConfiguration ),
406+ },
407+ }
408+
409+ for _ , tc := range loadTests {
410+ t .Run (tc .Name , tc .F (func (data testutils.ConfigTestData ) (Validator , error ) {
411+ // Since our test cases only define the expected configuration,
412+ // we need to create a new instance of that type for Load to parse the configuration into.
413+ actual := reflect .New (reflect .TypeOf (tc .Expected ).Elem ()).Interface ().(Validator )
414+
415+ var err error
416+ if data .Yaml != "" {
417+ testutils .WithYAMLFile (t , data .Yaml , func (file * os.File ) {
418+ err = Load (actual , LoadOptions {
419+ Flags : testFlags {
420+ configPath : file .Name (),
421+ explicitConfigPath : true ,
422+ },
423+ EnvOptions : EnvOptions {Environment : data .Env },
424+ })
425+ })
426+ } else {
427+ err = Load (actual , LoadOptions {Flags : testFlags {}, EnvOptions : EnvOptions {Environment : data .Env }})
428+ }
429+
430+ return actual , err
431+ }))
432+ }
433+
434+ t .Run ("Nil pointer argument" , func (t * testing.T ) {
435+ var config * struct { Validator }
436+
437+ err := Load (config , LoadOptions {})
438+ require .ErrorIs (t , err , ErrInvalidArgument )
439+ })
440+
441+ t .Run ("Nil argument" , func (t * testing.T ) {
442+ err := Load (nil , LoadOptions {})
443+ require .ErrorIs (t , err , ErrInvalidArgument )
444+ })
445+
446+ t .Run ("Non-struct pointer argument" , func (t * testing.T ) {
447+ var config nonStructValidator
448+
449+ err := Load (config , LoadOptions {})
450+ require .ErrorIs (t , err , ErrInvalidArgument )
451+ })
452+
453+ t .Run ("Explicit config; file does not exist" , func (t * testing.T ) {
454+ err := Load (& validateValid {}, LoadOptions {Flags : testFlags {explicitConfigPath : true }})
455+ require .ErrorIs (t , err , fs .ErrNotExist )
456+ })
457+ }
458+
327459func TestParseFlags (t * testing.T ) {
328460 t .Run ("Simple flags" , func (t * testing.T ) {
329461 originalArgs := os .Args
0 commit comments