require 'spec_helper' module Nucleon describe Config do include_context "nucleon_test" include_context "nucleon_config" #*************************************************************************** def config(*args, &code) test_object(Config, *args, &code) end #*************************************************************************** let(:config_object) { config(config_hash2) } #*************************************************************************** # Instance generators # Ensure the return of a Nucleon::Config object based on different inputs. # describe "#ensure" do it "creates with default values if nil given as the primary data source" do test_config Config.ensure(nil, config_hash1, true, true), config_hash1 test_config Config.ensure(nil, config_hash1, true, false), config_hash1 test_config Config.ensure(nil, config_hash1, false, true), config_hash1 test_config Config.ensure(nil, config_hash1, false, false), config_hash1 end it "creates via a basic merge of hash with forced overwrites" do test_config Config.ensure(config_hash2, config_hash1, true, true), config_hash_force_basic_merge end it "creates via a deep merge of hash with forced overwrites" do test_config Config.ensure(config_hash2, config_hash1, true, false), config_hash_force_deep_merge end it "creates via a basic merge of hash with no forced overwrites" do test_config Config.ensure(config_hash2, config_hash1, false, true), config_hash_no_force_basic_merge end it "creates via a deep merge of hash with no forced overwrites" do test_config Config.ensure(config_hash2, config_hash1, false, false), config_hash_no_force_deep_merge end it "creates via a basic merge of Config object with forced overwrites" do config = Config.ensure(config_object, config_hash1, true, true) test_config config, config_hash_force_basic_merge test_eq config == config_object, true end it "creates via a deep merge of Config object with forced overwrites" do config = Config.ensure(config_object, config_hash1, true, false) test_config config, config_hash_force_deep_merge test_eq config == config_object, true end it "creates via a basic merge of Config object with no forced overwrites" do config = Config.ensure(config_object, config_hash1, false, true) test_config config, config_hash_no_force_basic_merge test_eq config == config_object, true end it "creates via a deep merge of Config object with no forced overwrites" do config = Config.ensure(config_object, config_hash1, false, false) test_config config, config_hash_no_force_deep_merge test_eq config == config_object, true end end # Initialize a new configuration object with contextualized defaults from the global configuration option collection. # describe "#init" do it "creates with global contextual options only (multiple contexts, single hierarchy)" do test_config Config.init(nil, config_contexts1, config_context_hierarchy1, {}, true, true), config_context_options1 end it "creates with global contextual options only (multiple contexts, multiple hierarchies)" do test_config Config.init(nil, config_contexts2, config_context_hierarchy2, {}, true, true), config_context_options2 end it "creates with global contextual options only (single context, multiple hierarchies)" do test_config Config.init(nil, config_contexts3, config_context_hierarchy3, {}, true, true), config_context_options3 end it "creates via a basic merge of hash with forced overwrites (multiple contexts, single hierarchy)" do test_config Config.init(config_hash1, config_contexts1, config_context_hierarchy1, config_context_default_data, true, true), config_hash_context1_force_basic_merge end it "creates via a deep merge of hash with forced overwrites (multiple contexts, single hierarchy)" do test_config Config.init(config_hash1, config_contexts1, config_context_hierarchy1, config_context_default_data, true, false), config_hash_context1_force_deep_merge end it "creates via a basic merge of hash with no forced overwrites (multiple contexts, single hierarchy)" do test_config Config.init(config_hash1, config_contexts1, config_context_hierarchy1, config_context_default_data, false, true), config_hash_context1_no_force_basic_merge end it "creates via a deep merge of hash with no forced overwrites (multiple contexts, single hierarchy)" do test_config Config.init(config_hash1, config_contexts1, config_context_hierarchy1, config_context_default_data, false, false), config_hash_context1_no_force_deep_merge end it "creates via a basic merge of hash with forced overwrites (multiple contexts, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts2, config_context_hierarchy2, config_context_default_data, true, true), config_hash_context2_force_basic_merge end it "creates via a deep merge of hash with forced overwrites (multiple contexts, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts2, config_context_hierarchy2, config_context_default_data, true, false), config_hash_context2_force_deep_merge end it "creates via a basic merge of hash with no forced overwrites (multiple contexts, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts2, config_context_hierarchy2, config_context_default_data, false, true), config_hash_context2_no_force_basic_merge end it "creates via a deep merge of hash with no forced overwrites (multiple contexts, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts2, config_context_hierarchy2, config_context_default_data, false, false), config_hash_context2_no_force_deep_merge end it "creates via a basic merge of hash with forced overwrites (single context, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts3, config_context_hierarchy3, config_context_default_data, true, true), config_hash_context3_force_basic_merge end it "creates via a deep merge of hash with forced overwrites (single context, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts3, config_context_hierarchy3, config_context_default_data, true, false), config_hash_context3_force_deep_merge end it "creates via a basic merge of hash with no forced overwrites (single context, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts3, config_context_hierarchy3, config_context_default_data, false, true), config_hash_context3_no_force_basic_merge end it "creates via a deep merge of hash with no forced overwrites (single contexts, multiple hierarchies)" do test_config Config.init(config_hash1, config_contexts3, config_context_hierarchy3, config_context_default_data, false, false), config_hash_context3_no_force_deep_merge end end # Initialize a new configuration object with contextualized defaults from the # global configuration option collection (no hierarchical support). # describe "#init_flat" do it "creates with global contextual options only (multiple contexts)" do test_config Config.init_flat(nil, config_flat_contexts1, {}, true, true), config_flat_context_options1 end it "creates with global contextual options only (single context)" do test_config Config.init_flat(nil, config_flat_contexts2, {}, true, true), config_flat_context_options2 end end #*************************************************************************** # Constructor / Destructor # Initialize a new Nucleon core object # describe "#initialize" do it "creates with default values if nil given as the primary data source" do test_config config(nil, config_hash1, true, true), config_hash1 test_config config(nil, config_hash1, true, false), config_hash1 test_config config(nil, config_hash1, false, true), config_hash1 test_config config(nil, config_hash1, false, false), config_hash1 end it "creates via a basic merge of hash with forced overwrites" do test_config config(config_hash2, config_hash1, true, true), config_hash_force_basic_merge end it "creates via a deep merge of hash with forced overwrites" do test_config config(config_hash2, config_hash1, true, false), config_hash_force_deep_merge end it "creates via a basic merge of hash with no forced overwrites" do test_config config(config_hash2, config_hash1, false, true), config_hash_no_force_basic_merge end it "creates via a deep merge of hash with no forced overwrites" do test_config config(config_hash2, config_hash1, false, false), config_hash_no_force_deep_merge end it "creates via a basic merge of Config object with forced overwrites" do test_config config(config_object, config_hash1, true, true), config_hash_force_basic_merge end it "creates via a deep merge of Config object with forced overwrites" do test_config config(config_object, config_hash1, true, false), config_hash_force_deep_merge end it "creates via a basic merge of Config object with no forced overwrites" do test_config config(config_object, config_hash1, false, true), config_hash_no_force_basic_merge end it "creates via a deep merge of Config object with no forced overwrites" do test_config config(config_object, config_hash1, false, false), config_hash_no_force_deep_merge end end #*************************************************************************** # Checks # Check whether or not this configuration object is empty. # describe "#empty?" do it "returns false if properties are in the configuration object" do test_eq config(config_hash1, {}, true, true).empty?, false end it "returns true if the configuration object is empty" do test_eq config(nil, {}, true, true).empty?, true end end # Check whether or not this configuration object has a specific key. # describe "#has_key?" do it "is true if a top level key exists in the configuration object" do config(config_hash1, {}, true, true) do |config| test_eq config.has_key?("testkey"), true test_eq config.has_key?(:testkey), true end end it "is true if a nested key exists in the configuration object" do config(config_hash1, {}, true, true) do |config| test_eq config.has_key?([ "nestedkey", "a", "test1" ]), true test_eq config.has_key?([ :nestedkey, :a, :test1 ]), true test_eq config.has_key?([ "nestedkey", "a", :test1 ]), true test_eq config.has_key?([ :nestedkey, nil, :a, nil, :test1, nil ]), true end end it "is false if a top level key does not exist in the configuration object" do config(config_hash1, {}, true, true) do |config| test_eq config.has_key?("some_non_existent_key"), false test_eq config.has_key?(:some_non_existent_key), false end end it "is false if a nested key does not exist in the configuration object" do config(config_hash1, {}, true, true) do |config| test_eq config.has_key?([ "nestedkey", "test5" ]), false test_eq config.has_key?([ :nestedkey, :test5 ]), false test_eq config.has_key?([ "nestedkey", :test5 ]), false test_eq config.has_key?([ :nestedkey, nil, :test5, nil ]), false end end end #*************************************************************************** # Property accessors / modifiers # Return all of the keys for the configuration properties hash. # describe "#keys" do it "returns the top level property keys in the configuration object" do test_eq config(config_hash1, {}, true, true).keys, [ :testkey, :nestedkey, :other, :array ] test_eq config(config_hash2, {}, true, true).keys, [ :testkey1, :nestedkey, :other, :array ] end end # Fetch value for key path in the configuration object. # describe "#get" do it "returns an existing value for a top level property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true).get(:testkey, nil, false), 'testval' test_eq config(config_hash2, {}, true, true).get(:testkey1, nil, false), 'testval1' end it "returns an existing value for a nested property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, :test2 ], nil, false), [ 'no' ] test_eq config(config_hash1, {}, true, true).get([ :nestedkey, nil, :y, nil ], nil, false), 'again' test_eq config(config_hash2, {}, true, true).get([ :nestedkey, :a, :test1 ], nil, false), 'oh' test_eq config(config_hash2, {}, true, true).get([ :nestedkey, :a, nil, :test3, nil ], nil, false), true end it "returns a default value for a top level property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true).get(:testkey15, false, false), false test_eq config(config_hash1, {}, true, true).get(:testkey15, 'string', false), 'string' test_eq config(config_hash1, {}, true, true).get(:testkey15, :symbol, false), :symbol test_eq config(config_hash1, {}, true, true).get(:testkey15, [ :a, :b, :c ], false), [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true).get(:testkey15, { :a => :b }, false), { :a => :b } test_eq config(config_hash1, {}, true, true).get(:testkey15, false, :test), false test_eq config(config_hash1, {}, true, true).get(:testkey15, '42', :test), true test_eq config(config_hash1, {}, true, true).get(:testkey15, 'string', :string), 'string' test_eq config(config_hash1, {}, true, true).get(:testkey15, :string, :string), 'string' test_eq config(config_hash1, {}, true, true).get(:testkey15, :symbol, :symbol), :symbol test_eq config(config_hash1, {}, true, true).get(:testkey15, 'symbol', :symbol), :symbol test_eq config(config_hash1, {}, true, true).get(:testkey15, [ :a, :b, :c ], :array), [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true).get(:testkey15, :a, :array), [ :a ] test_eq config(config_hash1, {}, true, true).get(:testkey15, { :a => :b }, :hash), { :a => :b } test_eq config(config_hash1, {}, true, true).get(:testkey15, nil, :hash), {} end it "returns a default value for a nested property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], false, false), false test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], 'string', false), 'string' test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], :symbol, false), :symbol test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], [ :a, :b, :c ], false), [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], { :a => :b }, false), { :a => :b } test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], false, :test), false test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], '42', :test), true test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], 'string', :string), 'string' test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], :string, :string), 'string' test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], :symbol, :symbol), :symbol test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], 'symbol', :symbol), :symbol test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], [ :a, :b, :c ], :array), [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], :a, :array), [ :a ] test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], { :a => :b }, :hash), { :a => :b } test_eq config(config_hash1, {}, true, true).get([ :nestedkey, :a, nil, :unknown ], nil, :hash), {} end end # Fetch value for key path in the configuration object. # describe "#[]" do it "returns an existing value for a top level property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true)[:testkey, nil, false], 'testval' test_eq config(config_hash2, {}, true, true)[:testkey1, nil, false], 'testval1' end it "returns a default value for a top level property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true)[:testkey15, false, false], false test_eq config(config_hash1, {}, true, true)[:testkey15, 'string', false], 'string' test_eq config(config_hash1, {}, true, true)[:testkey15, :symbol, false], :symbol test_eq config(config_hash1, {}, true, true)[:testkey15, [ :a, :b, :c ], false], [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true)[:testkey15, { :a => :b }, false], { :a => :b } test_eq config(config_hash1, {}, true, true)[:testkey15, false, :test], false test_eq config(config_hash1, {}, true, true)[:testkey15, '42', :test], true test_eq config(config_hash1, {}, true, true)[:testkey15, 'string', :string], 'string' test_eq config(config_hash1, {}, true, true)[:testkey15, :string, :string], 'string' test_eq config(config_hash1, {}, true, true)[:testkey15, :symbol, :symbol], :symbol test_eq config(config_hash1, {}, true, true)[:testkey15, 'symbol', :symbol], :symbol test_eq config(config_hash1, {}, true, true)[:testkey15, [ :a, :b, :c ], :array], [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true)[:testkey15, :a, :array], [ :a ] test_eq config(config_hash1, {}, true, true)[:testkey15, { :a => :b }, :hash], { :a => :b } test_eq config(config_hash1, {}, true, true)[:testkey15, nil, :hash], {} end end # Fetch filtered array value for key path in the configuration object. # describe "#get_array" do it "returns an existing array for a top level property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true).get_array(:testkey, []), [ 'testval' ] test_eq config(config_hash2, {}, true, true).get_array(:testkey1, []), [ 'testval1' ] end it "returns an existing array for a nested property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true).get_array([ :nestedkey, :a, :test2 ], []), [ 'no' ] test_eq config(config_hash1, {}, true, true).get_array([ :nestedkey, nil, :y, nil ], []), [ 'again' ] test_eq config(config_hash2, {}, true, true).get_array([ :nestedkey, :a, :test1 ], []), [ 'oh' ] test_eq config(config_hash2, {}, true, true).get_array([ :nestedkey, :a, nil, :test3, nil ], []), [ true ] end it "returns a default array for a top level property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true).get_array(:testkey15, [ :a, :b, :c ]), [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true).get_array(:testkey15, :a), [ :a ] end it "returns a default array for a nested property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true).get_array([ :nestedkey, :a, nil, :unknown ], [ :a, :b, :c ]), [ :a, :b, :c ] test_eq config(config_hash1, {}, true, true).get_array([ :nestedkey, :a, nil, :unknown ], :a), [ :a ] end end # Fetch filtered hash value for key path in the configuration object. # describe "#get_hash" do it "returns an existing hash for a top level property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true).get_hash(:nestedkey, {}), { :a => { :test1 => 'oh', :test2 => [ 'no' ] }, :x => 'hello', :y => 'again', :z => 'im done now' } test_eq config(config_hash2, {}, true, true).get_hash(:nestedkey, {}), { :a => { :test1 => 'oh', :test2 => [ 'yes' ], :test3 => true }, :z => 'whew' } end it "returns an existing hash for a nested property from the configuration object if it exists" do test_eq config(config_hash1, {}, true, true).get_hash([ :nestedkey, :a ], {}), { :test1 => 'oh', :test2 => [ 'no' ] } test_eq config(config_hash1, {}, true, true).get_hash([ :nestedkey, nil, :y, nil ], {}), {} test_eq config(config_hash2, {}, true, true).get_hash([ :nestedkey, :a ], {}), { :test1 => 'oh', :test2 => [ 'yes' ], :test3 => true } test_eq config(config_hash2, {}, true, true).get_hash([ :nestedkey, :a, nil, :test3, nil ], {}), {} end it "returns a default hash for a top level property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true).get_hash(:testkey15, { :a => :b }), { :a => :b } test_eq config(config_hash1, {}, true, true).get_hash(:testkey15, nil), {} end it "returns a default hash for a nested property from the configuration object if it does not exist" do test_eq config(config_hash1, {}, true, true).get_hash([ :nestedkey, :a, nil, :unknown ], { :a => :b }), { :a => :b } test_eq config(config_hash1, {}, true, true).get_hash([ :nestedkey, :a, nil, :unknown ], nil), {} end end # Initialize value for key path in the configuration object if one does not # exist yet. # describe "#init" do it "sets a top level configuration property that does not exist yet" do test_eq config(config_hash1, {}, true, true).init(:other_property, 'testing').get(:other_property), 'testing' test_eq config(config_hash2, {}, true, true).init(:new_property, 'testing2').get(:new_property), 'testing2' end it "sets a nested configuration property that does not exist yet" do test_eq config(config_hash1, {}, true, true).init([ :nested_property, :abc ], [ 1, 2, 3 ]).get([ :nested_property, :abc ]), [ 1, 2, 3 ] test_eq config(config_hash2, {}, true, true).init([ :nested_property, :abc ], [ 1, 2, 3 ]).get([ :nested_property, :abc ]), [ 1, 2, 3 ] end it "leaves a top level configuration property untouched if it already exists" do test_eq config(config_hash1, {}, true, true).init(:other, 'testing').get(:other), [ 1, 2, 3, 4 ] test_eq config(config_hash2, {}, true, true).init(:other, 'testing').get(:other), 56 end it "leaves a nested configuration property untouched if it already exists" do test_eq config(config_hash1, {}, true, true).init([ :nestedkey, :a ], { :a => :b }).get([ :nestedkey, :a ]), { :test1 => 'oh', :test2 => [ 'no' ] } test_eq config(config_hash2, {}, true, true).init([ :nestedkey, :a ], { :a => :b }).get([ :nestedkey, :a ]), { :test1 => 'oh', :test2 => [ 'yes' ], :test3 => true } end end # Set value for key path in the configuration object. # describe "#set" do it "creates a configuration property with a specified value" do test_eq config(config_hash1, {}, true, true).set("other_property", "onething", false).get(:other_property), 'onething' test_eq config(config_hash2, {}, true, true).set(:other_property, { "a" => :b }, false).get([ :other_property, :a ]), :b end it "updates a configuration property with a specified value" do test_eq config(config_hash1, {}, true, true).set("other", "onething", false).get(:other), 'onething' test_eq config(config_hash2, {}, true, true).set(:nestedkey, { "a" => :b }, false).get([ :nestedkey, :a ]), :b end it "removes a configuration property containing a nil value" do test_eq config(config_hash1, {}, true, true).set(:array, nil, true).keys, [ :testkey, :nestedkey, :other ] test_eq config(config_hash2, {}, true, true).set(:array, nil, true).keys, [ :testkey1, :nestedkey, :other ] end end # Append a value for key path in the configuration object. # describe "#append" do it "appends values to a configuration property" do config do |config| config.append([ :my, :sequence ], 1) config.append([ :my, :sequence ], 3) config.append([ :my, :sequence ], 5) config.append([ :my, :sequence ], 7) test_eq config.get([ :my, :sequence]), [ 1, 3, 5, 7 ] end config do |config| config.append([ "my", :sequence ], [ 1, 2 ]) config.append([ :my, :sequence ], 3) config.append([ :my, :sequence ], [ 5, 5.5, 18 ]) config.append([ :my, "sequence" ], 7) test_eq config.get([ :my, "sequence" ]), [ 1, 2, 3, 5, 5.5, 18, 7 ] end end end # Prepend a value for key path in the configuration object. # describe "#prepend" do it "prepends values to a configuration property" do config do |config| config.prepend([ :my, :sequence ], 1) config.prepend([ :my, :sequence ], 3) config.prepend([ :my, :sequence ], 5) config.prepend([ :my, :sequence ], 7) test_eq config.get([ :my, :sequence]), [ 7, 5, 3, 1 ] end config do |config| config.prepend([ "my", :sequence ], [ 1, 2 ]) config.prepend([ :my, :sequence, nil ], 3) config.prepend([ :my, :sequence ], [ 5, 5.5, 18 ]) config.prepend([ :my, "sequence" ], 7) test_eq config.get([ :my, "sequence" ]), [ 7, 5, 5.5, 18, 3, 1, 2 ] end end it "prepends values to a configuration property with reversed arrays" do config do |config| config.prepend([ "my", :sequence ], [ 1, 2 ], true) config.prepend([ :my, :sequence ], 3) config.prepend([ :my, :sequence ], [ 5, 5.5, 18 ], true) config.prepend([ :my, "sequence" ], 7) test_eq config.get([ :my, "sequence" ]), [ 7, 18, 5.5, 5, 3, 2, 1 ] end config do |config| config.prepend([ "my", :sequence ], [ 1, 2 ], true) config.prepend([ :my, nil, :sequence ], 3) config.prepend([ :my, :sequence ], [ 5, 5.5, 18 ], false) config.prepend([ :my, "sequence" ], 7) test_eq config.get([ :my, "sequence" ]), [ 7, 5, 5.5, 18, 3, 2, 1 ] end end end # Set value for key in the configuration object. # describe "#[]=" do it "creates a configuration property with a specified value" do config(config_hash1, {}, true, true) do |config| config["other_property"] = "onething" test_eq config.get(:other_property), 'onething' end config(config_hash2, {}, true, true) do |config| config[:other_property] = { "a" => :b } test_eq config.get([ :other_property, :a ]), :b end end it "updates a configuration property with a specified value" do config(config_hash1, {}, true, true) do |config| config["other"] = "onething" test_eq config.get(:other), 'onething' end config(config_hash2, {}, true, true) do |config| config[:nestedkey] = { "a" => :b } test_eq config.get([ :nestedkey, :a ]), :b end end end # Delete key path from the configuration object. # describe "#delete" do it "removes a configuration property and returns existing value" do config(config_hash1, {}, true, true) do |config| test_eq config.delete(:other, nil), [ 1, 2, 3, 4 ] test_eq config.keys, [ :testkey, :nestedkey, :array ] end config(config_hash2, {}, true, true) do |config| test_eq config.delete(:array, nil), [ 12 ] test_eq config.keys, [ :testkey1, :nestedkey, :other ] end end it "returns a default value if configuration property doesn't exist" do test_eq config(config_hash1, {}, true, true).delete(:test57, :yummy), :yummy test_eq config(config_hash2, {}, true, true).delete(:test57, [ 1, 2, 3 ]), [ 1, 2, 3 ] end end # Clear all properties from the configuration object. # describe "#clear" do it "removes all the configuration properties from the object" do test_config config(config_hash1, {}, true, true).clear, {} test_config config(config_hash2, {}, true, true).clear, {} end end #*************************************************************************** # Import / Export # Import new property values into the configuration object. (override) # describe "#import" do # TODO: String and symbol lookup conditions (used in CORL) it "imports properties via a basic merge of hash with forced overwrites" do test_config config({}, {}, true, true).import([ config_hash1, config_hash2 ]), config_hash_force_basic_merge test_config config(config_hash1, {}, true, true).import(config_hash2), config_hash_force_basic_merge test_config config(config_hash1, {}, false, false).import(config_hash2, { :force => true, :basic => true }), config_hash_force_basic_merge end it "imports properties via a deep merge of hash with forced overwrites" do test_config config({}, {}, true, false).import([ config_hash1, config_hash2 ]), config_hash_force_deep_merge test_config config(config_hash1, {}, true, false).import(config_hash2), config_hash_force_deep_merge test_config config(config_hash1, {}, false, true).import(config_hash2, { :force => true, :basic => false }), config_hash_force_deep_merge end it "imports properties via a basic merge of hash with no forced overwrites" do test_config config({}, {}, false, true).import([ config_hash1, config_hash2 ]), config_hash_no_force_basic_merge test_config config(config_hash1, {}, false, true).import(config_hash2), config_hash_no_force_basic_merge test_config config(config_hash1, {}, true, false).import(config_hash2, { :force => false, :basic => true }), config_hash_no_force_basic_merge end it "imports properties via a deep merge of hash with no forced overwrites" do test_config config({}, {}, false, false).import([ config_hash1, config_hash2 ]), config_hash_no_force_deep_merge test_config config(config_hash1, {}, false, false).import(config_hash2), config_hash_no_force_deep_merge test_config config(config_hash1, {}, true, true).import(config_hash2, { :force => false, :basic => false }), config_hash_no_force_deep_merge end it "imports properties via a basic merge of Config object with forced overwrites" do test_config config({}, {}, true, true).import([ config_hash1, config_object ]), config_hash_force_basic_merge test_config config(config_hash1, {}, true, true).import(config_object), config_hash_force_basic_merge test_config config(config_hash1, {}, false, false).import(config_object, { :force => true, :basic => true }), config_hash_force_basic_merge end it "imports properties via a deep merge of Config object with forced overwrites" do test_config config({}, {}, true, false).import([ config_hash1, config_object ]), config_hash_force_deep_merge test_config config(config_hash1, {}, true, false).import(config_object), config_hash_force_deep_merge test_config config(config_hash1, {}, false, true).import(config_object, { :force => true, :basic => false }), config_hash_force_deep_merge end it "imports properties via a basic merge of Config object with no forced overwrites" do test_config config({}, {}, false, true).import([ config_hash1, config_object ]), config_hash_no_force_basic_merge test_config config(config_hash1, {}, false, true).import(config_object), config_hash_no_force_basic_merge test_config config(config_hash1, {}, true, false).import(config_object, { :force => false, :basic => true }), config_hash_no_force_basic_merge end it "imports properties via a deep merge of Config object with no forced overwrites" do test_config config({}, {}, false, false).import([ config_hash1, config_object ]), config_hash_no_force_deep_merge test_config config(config_hash1, {}, false, false).import(config_object), config_hash_no_force_deep_merge test_config config(config_hash1, {}, true, true).import(config_object, { :force => false, :basic => false }), config_hash_no_force_deep_merge end end # Set default property values in the configuration object if they don't exist. # describe "#defaults" do # TODO: String and symbol lookup conditions (used in CORL) it "imports default properties via a basic merge of hash with forced overwrites" do test_config config({}, {}, true, true).defaults([ config_hash2, config_hash1 ]), config_hash_force_basic_merge test_config config(config_hash2, {}, true, true).defaults(config_hash1), config_hash_force_basic_merge test_config config(config_hash2, {}, false, false).defaults(config_hash1, { :force => true, :basic => true }), config_hash_force_basic_merge end it "imports default properties via a deep merge of hash with forced overwrites" do test_config config({}, {}, true, false).defaults([ config_hash2, config_hash1 ]), config_hash_force_deep_merge test_config config(config_hash2, {}, true, false).defaults(config_hash1), config_hash_force_deep_merge test_config config(config_hash2, {}, false, true).defaults(config_hash1, { :force => true, :basic => false }), config_hash_force_deep_merge end it "imports default properties via a basic merge of hash with no forced overwrites" do test_config config({}, {}, false, true).defaults([ config_hash2, config_hash1 ]), config_hash_no_force_basic_merge test_config config(config_hash2, {}, false, true).defaults(config_hash1), config_hash_no_force_basic_merge test_config config(config_hash2, {}, true, false).defaults(config_hash1, { :force => false, :basic => true }), config_hash_no_force_basic_merge end it "imports default properties via a deep merge of hash with no forced overwrites" do test_config config({}, {}, false, false).defaults([ config_hash2, config_hash1 ]), config_hash_no_force_deep_merge test_config config(config_hash2, {}, false, false).defaults(config_hash1), config_hash_no_force_deep_merge test_config config(config_hash2, {}, true, true).defaults(config_hash1, { :force => false, :basic => false }), config_hash_no_force_deep_merge end it "imports default properties via a basic merge of Config object with forced overwrites" do test_config config({}, {}, true, true).defaults([ config_object, config_hash1 ]), config_hash_force_basic_merge test_config config(config_object, {}, true, true).defaults(config_hash1), config_hash_force_basic_merge test_config config(config_object, {}, false, false).defaults(config_hash1, { :force => true, :basic => true }), config_hash_force_basic_merge end it "imports default properties via a deep merge of Config object with forced overwrites" do test_config config({}, {}, true, false).defaults([ config_object, config_hash1 ]), config_hash_force_deep_merge test_config config(config_object, {}, true, false).defaults(config_hash1), config_hash_force_deep_merge test_config config(config_object, {}, false, true).defaults(config_hash1, { :force => true, :basic => false }), config_hash_force_deep_merge end it "imports default properties via a basic merge of Config object with no forced overwrites" do test_config config({}, {}, false, true).defaults([ config_object, config_hash1 ]), config_hash_no_force_basic_merge test_config config(config_object, {}, false, true).defaults(config_hash1), config_hash_no_force_basic_merge test_config config(config_object, {}, true, false).defaults(config_hash1, { :force => false, :basic => true }), config_hash_no_force_basic_merge end it "imports default properties via a deep merge of Config object with no forced overwrites" do test_config config({}, {}, false, false).defaults([ config_object, config_hash1 ]), config_hash_no_force_deep_merge test_config config(config_object, {}, false, false).defaults(config_hash1), config_hash_no_force_deep_merge test_config config(config_object, {}, true, true).defaults(config_hash1, { :force => false, :basic => false }), config_hash_no_force_deep_merge end end # Export properties into a regular hash object (cloned) # describe "#export" do it "returns all configuration properties as a symbolized hash" do test_config config(config_hash1, {}, true, true), config_hash1 test_config config(config_hash2, {}, true, true), config_hash2 end end #*************************************************************************** # Utilities # Return hash as a symbol map. # describe "#symbol_map" do it "returns a hash with recursively symbolized keys" do test_eq Config.symbol_map(config_mixed_hash), config_symbolized_hash end end # Return hash as a string map. # describe "#string_map" do it "returns a hash with recursively stringified keys" do test_eq Config.string_map(config_mixed_hash), config_stringified_hash end end #*************************************************************************** # Run a defined filter on a data object. # describe "#filter" do it "returns given value when not filtered" do test_eq Config.filter(true, false), true test_eq Config.filter("string", false), "string" test_eq Config.filter(:symbol, false), :symbol test_eq Config.filter([ "test", "array" ], false), [ "test", "array" ] test_eq Config.filter({ :a => :b }, false), { :a => :b } end it "returns a boolean when filtered for a test condition" do test_eq Config.filter(2 == 2, :test), true test_eq Config.filter(2 == 5, :test), false test_eq Config.filter("hello", :test), true test_eq Config.filter([ '1' ], :test), true test_eq Config.filter([], :test), false test_eq Config.filter({ "a" => "b" }, :test), true test_eq Config.filter({}, :test), false end it "returns a string when filtered for a string" do test_eq Config.filter("string", :string), "string" test_eq Config.filter(:symbol, :string), "symbol" test_eq Config.filter(true, :string), "true" test_eq Config.filter([ 1, 2, 3 ], :string), "[1, 2, 3]" test_eq Config.filter({ :a => :b }, :string), "{:a=>:b}" end it "returns a symbol when filtered for a symbol" do test_eq Config.filter("string", :symbol), :string test_eq Config.filter(:symbol, :symbol), :symbol test_eq Config.filter(true, :symbol), :true end it "returns an array when filtered for a array" do test_eq Config.filter(nil, :array), [] test_eq Config.filter("test", :array), [ "test" ] test_eq Config.filter([ "test", "array" ], :array), [ "test", "array" ] end it "returns a hash when filtered for a hash" do test_eq Config.filter(nil, :hash), {} test_eq Config.filter("test", :hash), {} test_eq Config.filter({ :a => :b }, :hash), { :a => :b } end end #*************************************************************************** # Ensure a data object is an array. # describe "#array" do it "returns a filtered array" do test_eq Config.filter(nil, :array), [] test_eq Config.filter("test", :array), [ "test" ] test_eq Config.filter([ "test", "array" ], :array), [ "test", "array" ] end end # Ensure a data object is a hash. # describe "#hash" do it "returns a filtered hash" do test_eq Config.filter(nil, :hash), {} test_eq Config.filter("test", :hash), {} test_eq Config.filter({ :a => :b }, :hash), { :a => :b } end end # Ensure a data object is a string. # describe "#string" do it "returns a filtered string" do test_eq Config.filter("string", :string), "string" test_eq Config.filter(:symbol, :string), "symbol" test_eq Config.filter(true, :string), "true" test_eq Config.filter([ 1, 2, 3 ], :string), "[1, 2, 3]" test_eq Config.filter({ :a => :b }, :string), "{:a=>:b}" end end # Ensure a data object is a symbol. # describe "#symbol" do it "returns a filtered symbol" do test_eq Config.filter("string", :symbol), :string test_eq Config.filter(:symbol, :symbol), :symbol test_eq Config.filter(true, :symbol), :true end end # Test a data object for emptiness and return boolean result. # describe "#test" do it "returns a filtered boolean" do test_eq Config.filter(2 == 2, :test), true test_eq Config.filter(2 == 5, :test), false test_eq Config.filter("hello", :test), true test_eq Config.filter([ '1' ], :test), true test_eq Config.filter([], :test), false test_eq Config.filter({ "a" => "b" }, :test), true test_eq Config.filter({}, :test), false end end end end