def test_handleCreateAccount_ok(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 100))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger King", "amount": 10, "time": "2019-02-13T10:00:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 90
            },
            "violations": []
        }
        expectedAccount = {
            "account": {
                "activeCard": True,
                "availableLimit": 90
            }
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)

        resultAccount = accountRepository.getByFilter(
            lambda _: True)[0].toDict()
        self.assertDictEqual(resultAccount, expectedAccount)
    def test_handleCreateAccount_InsufficientLimit(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 100))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger King", "amount": 101, "time": "2019-02-13T10:00:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 100
            },
            "violations": ['insufficient-limit']
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)

        transactions = transactionRepository.getByFilter(lambda _: True)
        self.assertListEqual([], transactions)
    def test_RepoGetByFilter_NotFound(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                super().__init__()

        model = TestModel()

        repo.add(model)

        result = repo.getByFilter(lambda x: False)

        self.assertListEqual([], result)
    def test_RepoGetByFilter_ok(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                super().__init__()

        model = TestModel()

        repo.add(model)

        result = repo.getByFilter(lambda x: x.id == model.id)

        self.assertListEqual([model], result)
    def test_RepoGetById_NotFound(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                super().__init__()

        model = TestModel()

        repo.add(model)

        result = repo.getById(uuid.uuid4())

        self.assertIsNone(result)
    def test_RepoGetById_ok(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                super().__init__()

        model = TestModel()

        repo.add(model)

        result = repo.getById(model.id)

        self.assertEqual(model, result)
    def test_RepoAdd_Existing(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                super().__init__()

        model = TestModel()

        rowsAffected = repo.add(model)
        self.assertEqual(1, rowsAffected)

        rowsAffected = repo.add(model)

        self.assertIsNotNone(model.id)
        self.assertIsNotNone(model.created_at)
        self.assertEqual(1, len(repo.dbSet))
        self.assertEqual(0, rowsAffected)
    def test_RepoUpdate_NotFound(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                self.verified = False
                super().__init__()

        model = TestModel()

        repo.add(model)
        self.assertIsNone(model.updated_at)
        self.assertFalse(model.verified)

        newModel = Model()
        affectedRows = repo.update(newModel)
        self.assertEqual(0, affectedRows)

        notUpdatedModel = repo.getById(model.id)
        self.assertIsNone(notUpdatedModel.updated_at)
        self.assertFalse(notUpdatedModel.verified)
    def test_RepoUpdate_ok(self):
        repo = InMemoryRepository()

        class TestModel(Model):
            def __init__(self):
                self.verified = False
                super().__init__()

        model = TestModel()

        repo.add(model)
        self.assertIsNone(model.updated_at)
        self.assertFalse(model.verified)

        model.verified = True
        affectedRows = repo.update(model)
        self.assertEqual(1, affectedRows)

        updatedModel = repo.getById(model.id)
        self.assertIsNotNone(updatedModel.updated_at)
        self.assertTrue(updatedModel.verified)
    def test_handleCreateAccount_DoubledTransaction(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 75))
        transactionRepository.add(
            Transaction(
                "Burger King", 10,
                datetime.strptime("2019-02-13T11:00:00.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))
        transactionRepository.add(
            Transaction(
                "Burger King", 10,
                datetime.strptime("2019-02-13T11:01:59.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger King", "amount": 10, "time": "2019-02-13T11:02:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 75
            },
            "violations": ['doubled-transaction']
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)
    def test_handleCreateAccount_AlreadyInitialized(self):

        repository = InMemoryRepository()
        repository.add(Account(True, 42))
        commandHandler = AccountCommandHandler(repository)
        command = CreateAccount(
            '{ "account": { "activeCard": true, "availableLimit": 100 } }')

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 42
            },
            "violations": ["account-already-initialized"]
        }

        result = commandHandler.handle_CreateAccount(command)

        self.assertDictEqual(expectedResult, result)

        emptyResults = repository.getByFilter(
            lambda account: account.availableLimit == 100)
        self.assertListEqual([], emptyResults)
    def test_handleCreateAccount_HighFrequencySmallInterval(self):

        accountRepository = InMemoryRepository()
        transactionRepository = InMemoryRepository()

        commandHandler = TransactionCommandHandler(transactionRepository,
                                                   accountRepository)

        accountRepository.add(Account(True, 75))
        transactionRepository.add(
            Transaction(
                "Burger King", 10,
                datetime.strptime("2019-02-13T11:00:00.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))
        transactionRepository.add(
            Transaction(
                "Burger Queen", 10,
                datetime.strptime("2019-02-13T11:01:00.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))
        transactionRepository.add(
            Transaction(
                "Burger Prince", 5,
                datetime.strptime("2019-02-13T11:01:59.000Z",
                                  '%Y-%m-%dT%H:%M:%S.%fZ')))

        command = AuthorizeTransaction(
            '{ "transaction": { "merchant": "Burger Pleb", "amount": 10, "time": "2019-02-13T10:00:00.000Z" } }'
        )

        expectedResult = {
            "account": {
                "activeCard": True,
                "availableLimit": 75
            },
            "violations": ['high-frequency-small-interval']
        }

        result = commandHandler.handle_AuthorizeTransaction(command)

        self.assertEqual(expectedResult, result)