def test_api_key_from_config_with_lesser_loading_order(self):
        """Similar to the previous test, but with apiKey key.
        """
        client_config = {
            'client': {
                'apiKey': {
                    'id': 'CLIENT_CONFIG_API_KEY_ID',
                    'secret': 'CLIENT_CONFIG_API_KEY_SECRET',
                }
            }
        }

        load_strategies = [
            # 1. We load the default configuration.
            LoadFileConfigStrategy('tests/assets/default_config.yml', must_exist=True),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            # 3. We load stormpath.yml file with client.apiKey.file
            LoadFileConfigStrategy('tests/assets/apiKeyApiKey.json'),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            LoadEnvConfigStrategy(prefix='STORMPATH'),
            # 7. Configuration provided through the SDK client
            #    constructor.
            ExtendConfigStrategy(extend_with=client_config)
        ]
        post_processing_strategies = [LoadAPIKeyFromConfigStrategy()]
        validation_strategies = [ValidateClientConfigStrategy()]

        cl = ConfigLoader(load_strategies, post_processing_strategies, validation_strategies)
        config = cl.load()

        self.assertEqual(config['client']['apiKey']['id'], 'CLIENT_CONFIG_API_KEY_ID')
        self.assertEqual(config['client']['apiKey']['secret'], 'CLIENT_CONFIG_API_KEY_SECRET')
    def test_api_key_file_from_config_with_lesser_loading_order(self):
        """Let's say we load the default configuration, and then
        stormpath.yml file with client.apiKey.file key. Then we provide
        API key ID and secret through environment variables - which
        have greater loading order than the stormpath.yml.
        """
        load_strategies = [
            # 1. We load the default configuration.
            LoadFileConfigStrategy('tests/assets/default_config.yml', must_exist=True),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            # 3. We load stormpath.yml file with client.apiKey.file
            LoadFileConfigStrategy('tests/assets/apiKeyFile.yml'),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            # 6. We load API key id and secret from environment
            #    variables.
            LoadEnvConfigStrategy(prefix='STORMPATH'),
            ExtendConfigStrategy(extend_with={})
        ]
        post_processing_strategies = [LoadAPIKeyFromConfigStrategy()]
        validation_strategies = [ValidateClientConfigStrategy()]

        cl = ConfigLoader(load_strategies, post_processing_strategies, validation_strategies)
        config = cl.load()

        self.assertEqual(config['client']['apiKey']['id'], 'greater order id')
        self.assertEqual(config['client']['apiKey']['secret'], 'greater order secret')
        self.assertFalse('file' in config['client']['apiKey'])
    def test_config_extending(self):
        client_config = {
            'client': {
                'apiKey': {
                    'id': 'CLIENT_CONFIG_API_KEY_ID',
                    'secret': 'CLIENT_CONFIG_API_KEY_SECRET',
                }
            }
        }

        load_strategies = [
            # 1. We load the default configuration.
            LoadFileConfigStrategy('tests/assets/default_config.yml', must_exist=True),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            LoadEnvConfigStrategy(prefix='STORMPATH'),
            # 7. Configuration provided through the SDK client
            #    constructor.
            ExtendConfigStrategy(extend_with=client_config)
        ]
        post_processing_strategies = [LoadAPIKeyFromConfigStrategy()]
        validation_strategies = [ValidateClientConfigStrategy()]

        cl = ConfigLoader(load_strategies, post_processing_strategies, validation_strategies)
        config = cl.load()

        self.assertTrue('baseUrl' in config['client'])
    def test_config_loader(self):
        cl = ConfigLoader(self.load_strategies, self.post_processing_strategies, self.validation_strategies)
        config = cl.load()

        self.assertEqual(config['client']['apiKey']['id'], 'CLIENT_CONFIG_API_KEY_ID')
        self.assertEqual(config['client']['apiKey']['secret'], 'CLIENT_CONFIG_API_KEY_SECRET')
        self.assertEqual(config['client']['cacheManager']['defaultTtl'], 302)
        self.assertEqual(config['client']['cacheManager']['defaultTti'], 303)
        self.assertEqual(config['application']['name'], 'CLIENT_CONFIG_APP')
    def test_api_key_from_config_with_lesser_loading_order(self):
        """Similar to the previous test, but with apiKey key. Post
        processing will move apiKey key to client.apiKey key if such
        key exists. Because of this, it is possible to override a key
        with greater loading order.
        """
        client_config = {
            'client': {
                'apiKey': {
                    'id': 'CLIENT_CONFIG_API_KEY_ID',
                    'secret': 'CLIENT_CONFIG_API_KEY_SECRET',
                }
            }
        }

        strategies = [
            # 1. We load the default configuration.
            LoadFileConfigStrategy('default_config.yml', must_exist=True),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            # 3. We load stormpath.yml file with client.apiKey.file
            LoadFileConfigStrategy('apiKeyApiKey.json'),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            LoadEnvConfigStrategy(prefix='STORMPATH'),
            # 7. Configuration provided through the SDK client
            #    constructor.
            ExtendConfigStrategy(extend_with=client_config),
            LoadAPIKeyFromConfigStrategy(),
            MoveAPIKeyToClientAPIKeyStrategy(),
            ValidateClientConfigStrategy(),
        ]

        cl = ConfigLoader(strategies)
        config = cl.load()

        # client.apiKey will have value user wouldn't expect. Maybe we
        # should do post processing after every load strategy and
        # delete apiKey at the end of each post processing?
        self.assertEqual(
            config['client']['apiKey']['id'], 'MY_JSON_CONFIG_API_KEY_ID')
        self.assertEqual(
            config['client']['apiKey']['secret'],
            'MY_JSON_CONFIG_API_KEY_SECRET')
    def test_api_key_file_from_config_with_lesser_loading_order(self):
        """Let's say we load the default configuration, and then
        stormpath.yml file with client.apiKey.file key. Then we provide
        API key ID and secret through environment variables - which
        have greater loading order than the stormpath.yml. Because
        of the post processing, API key we specified in environment
        variables will be overriden with API key specified in file
        defined in stormpath.yml.
        """
        os.environ["STORMPATH_CLIENT_APIKEY_ID"] = "greater order id"
        os.environ["STORMPATH_CLIENT_APIKEY_SECRET"] = "greater order secret"

        strategies = [
            # 1. We load the default configuration.
            LoadFileConfigStrategy('default_config.yml', must_exist=True),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            # 3. We load stormpath.yml file with client.apiKey.file
            LoadFileConfigStrategy('apiKeyFile.yml'),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            # 6. We load API key id and secret from environment
            #    variables.
            LoadEnvConfigStrategy(prefix='STORMPATH'),
            ExtendConfigStrategy(extend_with={}),
            LoadAPIKeyFromConfigStrategy(),
            MoveAPIKeyToClientAPIKeyStrategy(),
            ValidateClientConfigStrategy(),
        ]

        cl = ConfigLoader(strategies)
        config = cl.load()

        # client.apiKey will have value user wouldn't expect. Maybe we
        # should do post processing after every load strategy and
        # delete client.apiKey.file at the end of each post processing?
        self.assertEqual(
            config['client']['apiKey']['id'], 'API_KEY_PROPERTIES_ID')
        self.assertEqual(
            config['client']['apiKey']['secret'], 'API_KEY_PROPERTIES_SECRET')
        self.assertEqual(
            config['client']['apiKey']['file'], 'apiKey.properties')
    def test_config_extending(self):
        """There is only default config and the config provided through
        the client constructor. How should client config extend the
        default?
        """
        client_config = {
            'client': {
                'apiKey': {
                    'id': 'CLIENT_CONFIG_API_KEY_ID',
                    'secret': 'CLIENT_CONFIG_API_KEY_SECRET',
                }
            }
        }

        strategies = [
            # 1. We load the default configuration.
            LoadFileConfigStrategy('default_config.yml', must_exist=True),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            LoadAPIKeyConfigStrategy('i-do-not-exist'),
            LoadFileConfigStrategy('i-do-not-exist'),
            LoadEnvConfigStrategy(prefix='STORMPATH'),
            # 7. Configuration provided through the SDK client
            #    constructor.
            ExtendConfigStrategy(extend_with=client_config),
            LoadAPIKeyFromConfigStrategy(),
            MoveAPIKeyToClientAPIKeyStrategy(),
            ValidateClientConfigStrategy(),
        ]

        cl = ConfigLoader(strategies)
        config = cl.load()

        # Client config didn't contain 'baseUrl' key in the 'client.
        # When default config was updated by client config, the
        # 'baseUrl' key was deleted. This is how Python's update()
        # method work. Also, it seems that this is how jQuery's extend
        # work: http://jsfiddle.net/L11q3LqL/
        self.assertFalse('baseUrl' in config['client'])
 def test_empty_config_loader(self):
     cl = ConfigLoader()
     self.assertEqual(len(cl.load().keys()), 0)