def test_datetime_and_field_should_work(self):
        original_timestamp = timezone.now() - timedelta(hours=1)
        transaction = TransactionFactory(timestamp=original_timestamp)

        self.selenium.get(
            self.live_server_url +
            f"/admin/market/transaction/{transaction.id}/change/")
        self.assertIn(CONFIRM_CHANGE, self.selenium.page_source)

        # Set date via text input
        date_input = self.selenium.find_element(By.ID, "id_date")
        date_input.clear()
        date_input.send_keys("2021-01-01")
        self.assertEqual(date_input.get_attribute("value"), "2021-01-01")

        # Set timestamp via text input
        timestamp_date = self.selenium.find_element(By.ID, "id_timestamp_0")
        timestamp_date.clear()
        timestamp_date.send_keys(str(timezone.now().date()))
        timestamp_time = self.selenium.find_element(By.ID, "id_timestamp_1")
        timestamp_time.clear()
        timestamp_time.send_keys(str(timezone.now().time()))

        # Click save and continue
        self.selenium.find_element(By.NAME, "_continue").click()

        # Click Yes I'm Sure on confirmation page
        self.assertIn("Confirm", self.selenium.page_source)
        self.selenium.find_element(By.NAME, "_continue").click()

        transaction.refresh_from_db()
        self.assertEqual(str(transaction.date), "2021-01-01")
        self.assertTrue(transaction.timestamp > original_timestamp)
示例#2
0
 def test_should_not_delete_related_goals_or_user(self):
     user = UserFactory.create()
     transaction = TransactionFactory(user=user, goals=[GoalFactory.create(user=user)])
     transaction.delete()
     self.assertEqual(User.query.count(), 1)
     self.assertEqual(Transaction.query.count(), 0)
     self.assertEqual(Goal.query.count(), 1)
示例#3
0
    def test_withdraw_limit_exceeded(self, mock_withdraws):
        """withdraw: check if exception is raised when current date
        transaction + transaction value exceeds daily limit.
        """
        # given
        mock_withdraws.return_value = Decimal("40.00")
        account = self.create_account(
            balance=Decimal("50.00"),
            daily_withdraw_limit=Decimal("30.00"),
        )

        # this is better tested in the endpoints. Since here we are mocking
        # daily_value. We can probably remove it!
        transaction = TransactionFactory(
            transaction_type=TransactionTypeEnum.withdraw,
            transaction_date=datetime.today(),
            value=Decimal("30.00"),
            account=account)

        # when
        with self.assertRaises(ApiException) as error_context:
            withdraw(transaction)

        # then
        exception = error_context.exception
        self.assertEqual(exception.errors['details'], daily_withdraw_limit)
        exception.errors['details'] = None
        self.assertEqual(exception.errors, AccountFailures.limit_exceeded)
    def test_cannot_confirm_for_models_with_validator_on_model_field_if_validator_fails(
        self, ):
        # ItemSale.currency has a validator on it
        shop = ShopFactory()
        item = ItemFactory()
        InventoryFactory(shop=shop, item=item, quantity=10)
        transaction = TransactionFactory(shop=shop)
        data = {
            "transaction": transaction.id,
            "item": item.id,
            "quantity": 1,
            "currency": "FAKE",
            "total": 10.00,
            "_confirm_add": True,
            "_save": True,
        }
        response = self.client.post(reverse("admin:market_itemsale_add"), data)

        # Should show form with error and not confirmation page
        self.assertEqual(response.status_code, 200)
        expected_templates = [
            "admin/market/itemsale/change_form.html",
            "admin/market/change_form.html",
            "admin/change_form.html",
        ]
        self.assertEqual(response.template_name, expected_templates)
        self.assertEqual(ItemSale.objects.count(), 0)
        self.assertIn("error", str(response.rendered_content))
        self.assertIn("Invalid Currency", str(response.rendered_content))
        # Should still ask for confirmation
        self.assertIn(CONFIRM_ADD, response.rendered_content)
示例#5
0
    def test_get_transactions_filter_operation(self):
        """get_transactions: check if all account transactions are
        returned when filtering by transaction_type.
        """
        # given
        transactions = [
            TransactionFactory(transaction_type=TransactionTypeEnum.withdraw),
            TransactionFactory(transaction_type=TransactionTypeEnum.deposit)
        ]
        account = self.create_account(transactions=transactions)

        # when
        query = get_transactions(account.id,
                                 transaction_type=TransactionTypeEnum.withdraw)

        # then
        self.assertEqual(1, query.count())
示例#6
0
    def test_should_delete_users_goals_and_transactions(self):
        for i in range(2):
            user = UserFactory.create()
            GoalFactory.create(user=user, transactions=[TransactionFactory.create(user=user)])

        User.query.first().delete()
        self.assertEqual(User.query.count(), 1)
        self.assertEqual(Goal.query.count(), 1)
        self.assertEqual(Transaction.query.count(), 1)
示例#7
0
    def test_get_statement_paginated(self):
        """get: check if paginated statement is received for a valid account"""
        # given
        transactions = [
            TransactionFactory(transaction_date=datetime(2020, 12, 15)),
            TransactionFactory(transaction_date=datetime(2020, 12, 16)),
            TransactionFactory(transaction_date=datetime(2020, 12, 19))
        ]
        account = self.create_account(transactions=transactions)

        # when
        response = self.app.test_client().get(
            f'/accounts/statement/{account.id}?limit=1&offset=2',
        )
        response_data = json.loads(response.data)
        # then
        self.assert200(response)
        self.assertEqual(len(response_data['transactions']), 1)
        self.assertEqual(response_data['id'], account.id)
示例#8
0
    def run(self):
        """Runs this command."""
        if User.query.filter_by(email='*****@*****.**').first():
            print('Example user and data already exists.')
            return
        user = UserFactory.instance.create(first_name='John',
                                           last_name='Smith',
                                           email='*****@*****.**',
                                           password=('matcha'))
        user.save()
        print('Created user `[email protected]` with password `matcha`')
        amex = AccessTokenFactory.create(user=user,
                                         institution__name='amex').institution
        bofa = AccessTokenFactory.create(user=user,
                                         institution__name='bofa').institution
        print('Created example institutions: amex, boa')

        fake = Faker()

        goal = GoalFactory.create(user=user, name='Roth IRA', amount=5500)
        for i in range(51):
            TransactionFactory.create(goals=[goal],
                                      institution=amex,
                                      name=fake.bs(),
                                      amount=fake.pydecimal(left_digits=3,
                                                            right_digits=2),
                                      post_date=fake.date_time_this_year())
        goal.save()
        print('Created goal `{}` with `{}` Transactions'.format(goal.name, 50))

        goal = GoalFactory.create(user=user,
                                  name='Spend less on food',
                                  amount=1000)
        for j in range(51):
            TransactionFactory.create(goals=[goal],
                                      institution=bofa,
                                      name=fake.bs(),
                                      amount=fake.pydecimal(left_digits=3,
                                                            right_digits=2),
                                      post_date=fake.date_time_this_month())
        goal.save()
        print('Created goal `{}` with `{}` Transactions'.format(goal.name, 30))
示例#9
0
    def setUp(self):
        super().setUp()
        self.access_token = AccessTokenFactory.create()
        self.user = self.access_token.user
        self.token = generate_token_for_user(self.user)
        self.institution = self.access_token.institution
        self.transaction = TransactionFactory.create(
            user=self.user, institution=self.institution)

        self.deleted_user = UserFactory.create()
        self.nonexistent_token = generate_token_for_user(self.deleted_user)
        self.deleted_user.delete()
    def test_cannot_confirm_for_models_with_clean_overridden_if_clean_fails(
            self):
        shop = ShopFactory()
        item = ItemFactory()
        InventoryFactory(shop=shop, item=item, quantity=1)
        transaction = TransactionFactory(shop=shop)
        # Asking to buy more than the shop has in stock
        data = {
            "transaction": transaction.id,
            "item": item.id,
            "quantity": 9,
            "currency": "USD",
            "total": 10.00,
            "_confirm_add": True,
            "_save": True,
        }
        response = self.client.post(reverse("admin:market_itemsale_add"), data)

        # Should not have been added yet
        self.assertEqual(ItemSale.objects.count(), 0)

        # Ensure it shows the form and not the confirmation page
        self.assertEqual(response.status_code, 200)
        expected_templates = [
            "admin/market/itemsale/change_form.html",
            "admin/market/change_form.html",
            "admin/change_form.html",
        ]
        self.assertEqual(response.template_name, expected_templates)
        self.assertTrue("error" in str(response.content))
        self.assertTrue("Shop does not have enough of the item stocked" in str(
            response.content))

        # Should still be asking for confirmation
        self.assertIn(CONFIRM_ADD, response.rendered_content)

        # Fix the issue by buying only what shop has in stock
        data["quantity"] = 1
        # _confirm_add would still be in the POST data
        response = self.client.post(reverse("admin:market_itemsale_add"), data)

        # Should show confirmation page
        # Ensure not redirected (confirmation page does not redirect)
        self.assertEqual(response.status_code, 200)
        expected_templates = [
            "admin/market/itemsale/change_confirmation.html",
            "admin/market/change_confirmation.html",
            "admin/change_confirmation.html",
        ]
        self.assertEqual(response.template_name, expected_templates)

        self._assertSubmitHtml(rendered_content=response.rendered_content)
示例#11
0
    def test_get_transactions_filter_date(self):
        """get_transactions: check if corrent number of transactions are
        returned when filtering by date.
        """
        # given
        transactions = [
            TransactionFactory(transaction_type=TransactionTypeEnum.withdraw,
                               transaction_date=datetime(2020, 12, 15)),
            TransactionFactory(transaction_type=TransactionTypeEnum.deposit,
                               transaction_date=datetime(2020, 12, 16)),
            TransactionFactory(transaction_type=TransactionTypeEnum.deposit,
                               transaction_date=datetime(2020, 12, 19))
        ]

        account = self.create_account(transactions=transactions)

        # when
        filters = Filters(_from='2020-12-12', _to='2020-12-18')
        query = get_transactions(account.id, filters=filters)

        # then
        self.assertEqual(2, query.count())
示例#12
0
    def test_get_statement_filter_by_period(self):
        """get: check if statement with transactions per period is received
        for a valid account
        """
        # given
        transactions = [
            TransactionFactory(transaction_date=datetime(2020, 12, 15)),
            TransactionFactory(transaction_date=datetime(2020, 12, 16)),
            TransactionFactory(transaction_date=datetime(2020, 12, 19))
        ]
        account = self.create_account(transactions=transactions)

        # when
        response = self.app.test_client().get(
            f'/accounts/statement/{account.id}?from=2020-12-14&to=2020-12-17',
        )
        response_data = json.loads(response.data)

        # then
        self.assert200(response)
        self.assertEqual(len(response_data['transactions']), 2)
        self.assertEqual(response_data['id'], account.id)
示例#13
0
 def test_get_transactions_with_no_institution_should_succeed(self):
     other_transaction = TransactionFactory.create(user=self.user)
     url = url_for('transactions_api.get_transactions')
     headers = self.create_headers(user=self.user)
     response = self.request_endpoint('GET', url, headers,
                                      status.HTTP_200_OK)
     self.assertListEqual(
         json.loads(response.data.decode('utf-8'))['transactions'],
         list(
             map(snake_to_camel_case_dict, [
                 self.transaction.serialize(),
                 other_transaction.serialize()
             ])))
示例#14
0
    def test_get_today_withdraws(self):
        """get_today_withdraws: check if only current date withdraws are
        returned.
        """
        # given
        value = Decimal("5.00")
        transactions = [
            TransactionFactory(transaction_type=TransactionTypeEnum.withdraw,
                               transaction_date=datetime.today(),
                               value=value),
            TransactionFactory(transaction_type=TransactionTypeEnum.withdraw,
                               transaction_date=datetime.today(),
                               value=value),
            TransactionFactory(transaction_type=TransactionTypeEnum.withdraw,
                               transaction_date=datetime(2020, 12, 19),
                               value=value)
        ]
        account = self.create_account(transactions=transactions)

        # when
        current_total = get_today_withdraws(account.id)

        # then
        self.assertEqual(2 * value, current_total)
示例#15
0
    def test_get_transactions_no_filters(self):
        """get_transactions: check if all account transactions are
        returned when no filter is provided.
        """
        # given
        number_transactions = 2
        account = self.create_account(
            balance=Decimal("20.00"),
            transactions=TransactionFactory.create_batch(number_transactions))

        # when
        query = get_transactions(account.id)

        # then
        self.assertEqual(number_transactions, query.count())
示例#16
0
    def test_confirm_change_of_datetime_and_date_field(self):
        transaction = TransactionFactory()
        original_date = transaction.date
        original_timestamp = transaction.timestamp
        data = {
            "id": transaction.id,
            "date": "2021-01-01",
            "timestamp_0": "2021-01-01",
            "timestamp_1": "12:30:00",
            "currency": "USD",
            "shop": transaction.shop.id,
            "total": 0,
            "_confirm_change": True,
            "csrfmiddlewaretoken": "fake token",
            "_continue": True,
        }
        response = self.client.post(
            f"/admin/market/transaction/{transaction.id}/change/", data
        )
        # Ensure not redirected (confirmation page does not redirect)
        self.assertEqual(response.status_code, 200)
        expected_templates = [
            "admin/market/transaction/change_confirmation.html",
            "admin/market/change_confirmation.html",
            "admin/change_confirmation.html",
        ]
        self.assertEqual(response.template_name, expected_templates)

        self._assertSubmitHtml(
            rendered_content=response.rendered_content, save_action="_continue"
        )

        # Hasn't changed item yet
        transaction.refresh_from_db()
        self.assertEqual(transaction.date, original_date)
        self.assertEqual(transaction.timestamp, original_timestamp)

        # Selecting to "Yes, I'm sure" on the confirmation page
        # Would post to the same endpoint
        del data["_confirm_change"]
        response = self.client.post(
            f"/admin/market/transaction/{transaction.id}/change/", data
        )
        # will show the change page for this transaction
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response.url, f"/admin/market/transaction/{transaction.id}/change/"
        )
        # Should not be the confirmation page, we already confirmed change
        self.assertNotEqual(response.templates, expected_templates)
        self.assertEqual(Transaction.objects.count(), 1)

        transaction.refresh_from_db()
        self.assertEqual(str(transaction.date), "2021-01-01")
        self.assertEqual(str(transaction.timestamp.date()), "2021-01-01")
        self.assertEqual(str(transaction.timestamp.time()), "12:30:00")
示例#17
0
    def test_get_statement(self):
        """get: check if statement is received for a valid account"""
        # given
        number_transactions = 5
        account = self.create_account(
            transactions=TransactionFactory.create_batch(number_transactions)
        )

        # when
        response = self.app.test_client().get(
            f'/accounts/statement/{account.id}',
        )
        response_data = json.loads(response.data)
        # then
        self.assert200(response)
        self.assertEqual(len(response_data['transactions']), len(account.transactions))
        self.assertEqual(response_data['id'], account.id)
示例#18
0
    def test_withdraw(self, mock_withdraws):
        """withdraw: check if withdraw operation is successfully executed."""
        # given
        mock_withdraws.return_value = Decimal("20.00")
        transaction = TransactionFactory(
            transaction_type=TransactionTypeEnum.withdraw,
            transaction_date=datetime.today(),
            value=Decimal("10.00"),
        )
        account = self.create_account(balance=Decimal("50.00"),
                                      transactions=[transaction],
                                      daily_withdraw_limit=Decimal("30.00"))

        # when
        withdraw(transaction)

        # then
        self.assertEqual(account.balance, Decimal("40.00"))
    def test_can_confirm_for_models_with_validator_on_model_field(
            self, _mock_clean):
        # ItemSale.currency has a validator on it
        item = ItemFactory()
        transaction = TransactionFactory()
        data = {
            "transaction": transaction.id,
            "item": item.id,
            "quantity": 1,
            "currency": "USD",
            "total": 10.00,
            "_confirm_add": True,
            "_save": True,
        }
        response = self.client.post(reverse("admin:market_itemsale_add"), data)

        # Should not have been added yet
        self.assertEqual(ItemSale.objects.count(), 0)

        # Ensure not redirected (confirmation page does not redirect)
        self.assertEqual(response.status_code, 200)
        expected_templates = [
            "admin/market/itemsale/change_confirmation.html",
            "admin/market/change_confirmation.html",
            "admin/change_confirmation.html",
        ]
        self.assertEqual(response.template_name, expected_templates)

        self._assertSubmitHtml(rendered_content=response.rendered_content)

        # Confirmation page would not have the _confirm_add sent on submit
        del data["_confirm_add"]
        # Selecting to "Yes, I'm sure" on the confirmation page
        # Would post to the same endpoint
        response = self.client.post(reverse("admin:market_itemsale_add"), data)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.url, "/admin/market/itemsale/")
        self.assertEqual(ItemSale.objects.count(), 1)

        # Ensure that the date and timestamp saved correctly
        item_sale = ItemSale.objects.first()
        self.assertEqual(item_sale.transaction, transaction)
        self.assertEqual(item_sale.item, item)
        self.assertEqual(item_sale.currency, "USD")
示例#20
0
    def test_withdraw_insuficient_funds(self, mock_withdraws):
        """withdraw: check if exception is raised when there's no enough
        funds.
        """
        # given
        mock_withdraws.return_value = Decimal("0.00")
        account = self.create_account(balance=Decimal("20.00"),
                                      daily_withdraw_limit=Decimal("30.00"))
        transaction = TransactionFactory(
            transaction_type=TransactionTypeEnum.withdraw,
            transaction_date=datetime.today(),
            value=Decimal("30.00"),
            account=account)

        # when
        with self.assertRaises(ApiException) as error_context:
            withdraw(transaction)

        # then
        exception = error_context.exception
        self.assertEqual(exception.errors, AccountFailures.insufficiente_funds)
示例#21
0
    def test_withdraw_blocked_acount(self, mock_withdraws):
        """withdraw: check if exception is raised when trying to take money
        from a blocked account.
        """
        # given
        mock_withdraws.return_value = Decimal("0.00")
        account = self.create_account(daily_withdraw_limit=Decimal("30.00"),
                                      active_flag=False)

        transaction = TransactionFactory(
            transaction_type=TransactionTypeEnum.withdraw,
            transaction_date=datetime.today(),
            value=Decimal("1.00"),
            account=account)

        # when
        with self.assertRaises(ApiException) as error_context:
            withdraw(transaction)

        # then
        exception = error_context.exception
        self.assertEqual(exception.errors, AccountFailures.blocked_account)
示例#22
0
 def test_should_delete_transactions_belonging_to_it(self):
     institution = TransactionFactory.create().institution
     institution.delete()
     self.assertEqual(Institution.query.count(), 0)
     self.assertEqual(Transaction.query.count(), 0)
示例#23
0
def transaction_factory(session):
    yield TransactionFactory(session)