mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-04-29 01:42:37 +02:00
Fix order of participants in the statistics page (#608)
This fixes #607 and add a test case for this bug. It also renames participants in test cases to avoid alphabetical ordering. Inserting participants in alphabetical order is a special case, because ordering by ID will be the same as ordering by name. This is a bad idea in test cases, as #607 has shown.
This commit is contained in:
parent
15ab04e636
commit
795efd6b58
2 changed files with 100 additions and 110 deletions
|
@ -9,7 +9,7 @@
|
||||||
<th class="balance-value">{{ _("Balance") }}</th>
|
<th class="balance-value">{{ _("Balance") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{% for stat in members_stats| sort(attribute='member.name') %}
|
{% for stat in members_stats|sort(attribute='member.name') %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="balance-name">{{ stat.member.name }}</td>
|
<td class="balance-name">{{ stat.member.name }}</td>
|
||||||
<td class="balance-value {% if stat.balance|round(2) > 0 %}positive{% elif stat.balance|round(2) < 0 %}negative{% endif %}">
|
<td class="balance-value {% if stat.balance|round(2) > 0 %}positive{% elif stat.balance|round(2) < 0 %}negative{% endif %}">
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
<table id="bill_table" class="split_bills table table-striped ml-md-n3">
|
<table id="bill_table" class="split_bills table table-striped ml-md-n3">
|
||||||
<thead><tr><th class="d-md-none">{{ _("Who?") }}</th><th>{{ _("Paid") }}</th><th>{{ _("Spent") }}</th></tr></thead>
|
<thead><tr><th class="d-md-none">{{ _("Who?") }}</th><th>{{ _("Paid") }}</th><th>{{ _("Spent") }}</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for stat in members_stats %}
|
{% for stat in members_stats|sort(attribute='member.name') %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="d-md-none">{{ stat.member.name }}</td>
|
<td class="d-md-none">{{ stat.member.name }}</td>
|
||||||
<td>{{ "%0.2f"|format(stat.paid) }}</td>
|
<td>{{ "%0.2f"|format(stat.paid) }}</td>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import datetime
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
@ -141,24 +142,24 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
|
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
self.client.post(
|
self.client.post(
|
||||||
"/raclette/invite", data={"emails": "alexis@notmyidea.org"}
|
"/raclette/invite", data={"emails": "zorglub@notmyidea.org"}
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(len(outbox), 2)
|
self.assertEqual(len(outbox), 2)
|
||||||
self.assertEqual(outbox[0].recipients, ["raclette@notmyidea.org"])
|
self.assertEqual(outbox[0].recipients, ["raclette@notmyidea.org"])
|
||||||
self.assertEqual(outbox[1].recipients, ["alexis@notmyidea.org"])
|
self.assertEqual(outbox[1].recipients, ["zorglub@notmyidea.org"])
|
||||||
|
|
||||||
# sending a message to multiple persons
|
# sending a message to multiple persons
|
||||||
with self.app.mail.record_messages() as outbox:
|
with self.app.mail.record_messages() as outbox:
|
||||||
self.client.post(
|
self.client.post(
|
||||||
"/raclette/invite",
|
"/raclette/invite",
|
||||||
data={"emails": "alexis@notmyidea.org, toto@notmyidea.org"},
|
data={"emails": "zorglub@notmyidea.org, toto@notmyidea.org"},
|
||||||
)
|
)
|
||||||
|
|
||||||
# only one message is sent to multiple persons
|
# only one message is sent to multiple persons
|
||||||
self.assertEqual(len(outbox), 1)
|
self.assertEqual(len(outbox), 1)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
outbox[0].recipients, ["alexis@notmyidea.org", "toto@notmyidea.org"]
|
outbox[0].recipients, ["zorglub@notmyidea.org", "toto@notmyidea.org"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# mail address checking
|
# mail address checking
|
||||||
|
@ -170,7 +171,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
# mixing good and wrong addresses shouldn't send any messages
|
# mixing good and wrong addresses shouldn't send any messages
|
||||||
with self.app.mail.record_messages() as outbox:
|
with self.app.mail.record_messages() as outbox:
|
||||||
self.client.post(
|
self.client.post(
|
||||||
"/raclette/invite", data={"emails": "alexis@notmyidea.org, alexis"}
|
"/raclette/invite", data={"emails": "zorglub@notmyidea.org, zorglub"}
|
||||||
) # not valid
|
) # not valid
|
||||||
|
|
||||||
# only one message is sent to multiple persons
|
# only one message is sent to multiple persons
|
||||||
|
@ -360,7 +361,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
result.data.decode("utf-8"),
|
result.data.decode("utf-8"),
|
||||||
)
|
)
|
||||||
|
|
||||||
result = self.client.post("/raclette/members/add", data={"name": "alexis"})
|
result = self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
|
|
||||||
result = self.client.get("/raclette/")
|
result = self.client.get("/raclette/")
|
||||||
|
|
||||||
|
@ -374,11 +375,11 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.login("raclette")
|
self.login("raclette")
|
||||||
|
|
||||||
# adds a member to this project
|
# adds a member to this project
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
||||||
|
|
||||||
# adds him twice
|
# adds him twice
|
||||||
result = self.client.post("/raclette/members/add", data={"name": "alexis"})
|
result = self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
|
|
||||||
# should not accept him
|
# should not accept him
|
||||||
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
||||||
|
@ -449,11 +450,11 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.login("raclette")
|
self.login("raclette")
|
||||||
|
|
||||||
# adds a member to this project
|
# adds a member to this project
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
alexis = models.Project.query.get("raclette").members[-1]
|
zorglub = models.Project.query.get("raclette").members[-1]
|
||||||
|
|
||||||
# should not have any bills
|
# should not have any bills
|
||||||
self.assertFalse(alexis.has_bills())
|
self.assertFalse(zorglub.has_bills())
|
||||||
|
|
||||||
# bound him to a bill
|
# bound him to a bill
|
||||||
self.client.post(
|
self.client.post(
|
||||||
|
@ -461,22 +462,22 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
data={
|
data={
|
||||||
"date": "2011-08-10",
|
"date": "2011-08-10",
|
||||||
"what": "fromage à raclette",
|
"what": "fromage à raclette",
|
||||||
"payer": alexis.id,
|
"payer": zorglub.id,
|
||||||
"payed_for": [alexis.id],
|
"payed_for": [zorglub.id],
|
||||||
"amount": "25",
|
"amount": "25",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# should have a bill now
|
# should have a bill now
|
||||||
alexis = models.Project.query.get("raclette").members[-1]
|
zorglub = models.Project.query.get("raclette").members[-1]
|
||||||
self.assertTrue(alexis.has_bills())
|
self.assertTrue(zorglub.has_bills())
|
||||||
|
|
||||||
def test_member_delete_method(self):
|
def test_member_delete_method(self):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
self.login("raclette")
|
self.login("raclette")
|
||||||
|
|
||||||
# adds a member to this project
|
# adds a member to this project
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
|
|
||||||
# try to remove the member using GET method
|
# try to remove the member using GET method
|
||||||
response = self.client.get("/raclette/members/1/delete")
|
response = self.client.get("/raclette/members/1/delete")
|
||||||
|
@ -604,7 +605,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add two persons
|
# add two persons
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
|
|
||||||
members_ids = [m.id for m in models.Project.query.get("raclette").members]
|
members_ids = [m.id for m in models.Project.query.get("raclette").members]
|
||||||
|
@ -712,7 +713,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add two persons
|
# add two persons
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post(
|
self.client.post(
|
||||||
"/raclette/members/add", data={"name": "freddy familly", "weight": 4}
|
"/raclette/members/add", data={"name": "freddy familly", "weight": 4}
|
||||||
)
|
)
|
||||||
|
@ -749,8 +750,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# Add two times the same person (with a space at the end).
|
# Add two times the same person (with a space at the end).
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis "})
|
self.client.post("/raclette/members/add", data={"name": "zorglub "})
|
||||||
members = models.Project.query.get("raclette").members
|
members = models.Project.query.get("raclette").members
|
||||||
|
|
||||||
self.assertEqual(len(members), 1)
|
self.assertEqual(len(members), 1)
|
||||||
|
@ -759,7 +760,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add two persons
|
# add two persons
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata", "weight": 1})
|
self.client.post("/raclette/members/add", data={"name": "tata", "weight": 1})
|
||||||
|
|
||||||
resp = self.client.get("/raclette/")
|
resp = self.client.get("/raclette/")
|
||||||
|
@ -776,9 +777,9 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# Add one user and edit it to have a negative share
|
# Add one user and edit it to have a negative share
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
resp = self.client.post(
|
resp = self.client.post(
|
||||||
"/raclette/members/1/edit", data={"name": "alexis", "weight": -1}
|
"/raclette/members/1/edit", data={"name": "zorglub", "weight": -1}
|
||||||
)
|
)
|
||||||
|
|
||||||
# An error should be generated, and its weight should still be 1.
|
# An error should be generated, and its weight should still be 1.
|
||||||
|
@ -790,7 +791,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
|
|
||||||
|
@ -846,7 +847,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
new_data = {
|
new_data = {
|
||||||
"name": "Super raclette party!",
|
"name": "Super raclette party!",
|
||||||
"contact_email": "alexis@notmyidea.org",
|
"contact_email": "zorglub@notmyidea.org",
|
||||||
"password": "didoudida",
|
"password": "didoudida",
|
||||||
"logging_preference": LoggingMode.ENABLED.value,
|
"logging_preference": LoggingMode.ENABLED.value,
|
||||||
"default_currency": "USD",
|
"default_currency": "USD",
|
||||||
|
@ -898,11 +899,11 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis", "weight": 2})
|
self.client.post("/raclette/members/add", data={"name": "zorglub", "weight": 2})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
# Add a member with a balance=0 :
|
# Add a member with a balance=0 :
|
||||||
self.client.post("/raclette/members/add", data={"name": "toto"})
|
self.client.post("/raclette/members/add", data={"name": "pépé"})
|
||||||
|
|
||||||
# create bills
|
# create bills
|
||||||
self.client.post(
|
self.client.post(
|
||||||
|
@ -939,45 +940,34 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
response = self.client.get("/raclette/statistics")
|
response = self.client.get("/raclette/statistics")
|
||||||
first_cell = '<td class="d-md-none">'
|
regex = r"<td class=\"d-md-none\">{}</td>\s+<td>{}</td>\s+<td>{}</td>"
|
||||||
indent = "\n "
|
self.assertRegex(
|
||||||
self.assertIn(
|
response.data.decode("utf-8"), regex.format("zorglub", "20.00", "31.67"),
|
||||||
first_cell
|
|
||||||
+ "alexis</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>20.00</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>31.67</td>\n",
|
|
||||||
response.data.decode("utf-8"),
|
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertRegex(
|
||||||
first_cell
|
response.data.decode("utf-8"), regex.format("fred", "20.00", "5.83"),
|
||||||
+ "fred</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>20.00</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>5.83</td>\n",
|
|
||||||
response.data.decode("utf-8"),
|
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertRegex(
|
||||||
first_cell
|
response.data.decode("utf-8"), regex.format("tata", "0.00", "2.50"),
|
||||||
+ "tata</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>0.00</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>2.50</td>\n",
|
|
||||||
response.data.decode("utf-8"),
|
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertRegex(
|
||||||
first_cell
|
response.data.decode("utf-8"), regex.format("pépé", "0.00", "0.00"),
|
||||||
+ "toto</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>0.00</td>"
|
|
||||||
+ indent
|
|
||||||
+ "<td>0.00</td>\n",
|
|
||||||
response.data.decode("utf-8"),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check that the order of participants in the sidebar table is the
|
||||||
|
# same as in the main table.
|
||||||
|
order = ["fred", "pépé", "tata", "zorglub"]
|
||||||
|
regex1 = r".*".join(
|
||||||
|
r"<td class=\"balance-name\">{}</td>".format(name) for name in order
|
||||||
|
)
|
||||||
|
regex2 = r".*".join(
|
||||||
|
r"<td class=\"d-md-none\">{}</td>".format(name) for name in order
|
||||||
|
)
|
||||||
|
# Build the regexp ourselves to be able to pass the DOTALL flag
|
||||||
|
# (so that ".*" matches newlines)
|
||||||
|
self.assertRegex(response.data.decode("utf-8"), re.compile(regex1, re.DOTALL))
|
||||||
|
self.assertRegex(response.data.decode("utf-8"), re.compile(regex2, re.DOTALL))
|
||||||
|
|
||||||
def test_settle_page(self):
|
def test_settle_page(self):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
response = self.client.get("/raclette/settle_bills")
|
response = self.client.get("/raclette/settle_bills")
|
||||||
|
@ -987,11 +977,11 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
# Add a member with a balance=0 :
|
# Add a member with a balance=0 :
|
||||||
self.client.post("/raclette/members/add", data={"name": "toto"})
|
self.client.post("/raclette/members/add", data={"name": "pépé"})
|
||||||
|
|
||||||
# create bills
|
# create bills
|
||||||
self.client.post(
|
self.client.post(
|
||||||
|
@ -1042,7 +1032,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis"})
|
self.client.post("/raclette/members/add", data={"name": "zorglub"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
|
|
||||||
|
@ -1095,7 +1085,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis", "weight": 2})
|
self.client.post("/raclette/members/add", data={"name": "zorglub", "weight": 2})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "pépé"})
|
self.client.post("/raclette/members/add", data={"name": "pépé"})
|
||||||
|
@ -1154,15 +1144,15 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"amount": 200.0,
|
"amount": 200.0,
|
||||||
"payer_name": "fred",
|
"payer_name": "fred",
|
||||||
"payer_weight": 1.0,
|
"payer_weight": 1.0,
|
||||||
"owers": ["alexis", "tata"],
|
"owers": ["zorglub", "tata"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"date": "2016-12-31",
|
"date": "2016-12-31",
|
||||||
"what": "fromage \xe0 raclette",
|
"what": "fromage \xe0 raclette",
|
||||||
"amount": 10.0,
|
"amount": 10.0,
|
||||||
"payer_name": "alexis",
|
"payer_name": "zorglub",
|
||||||
"payer_weight": 2.0,
|
"payer_weight": 2.0,
|
||||||
"owers": ["alexis", "fred", "tata", "p\xe9p\xe9"],
|
"owers": ["zorglub", "fred", "tata", "p\xe9p\xe9"],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.assertEqual(json.loads(resp.data.decode("utf-8")), expected)
|
self.assertEqual(json.loads(resp.data.decode("utf-8")), expected)
|
||||||
|
@ -1172,8 +1162,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
expected = [
|
expected = [
|
||||||
"date,what,amount,payer_name,payer_weight,owers",
|
"date,what,amount,payer_name,payer_weight,owers",
|
||||||
"2017-01-01,refund,13.33,tata,1.0,fred",
|
"2017-01-01,refund,13.33,tata,1.0,fred",
|
||||||
'2016-12-31,red wine,200.0,fred,1.0,"alexis, tata"',
|
'2016-12-31,red wine,200.0,fred,1.0,"zorglub, tata"',
|
||||||
'2016-12-31,fromage à raclette,10.0,alexis,2.0,"alexis, fred, tata, pépé"',
|
'2016-12-31,fromage à raclette,10.0,zorglub,2.0,"zorglub, fred, tata, pépé"',
|
||||||
]
|
]
|
||||||
received_lines = resp.data.decode("utf-8").split("\n")
|
received_lines = resp.data.decode("utf-8").split("\n")
|
||||||
|
|
||||||
|
@ -1187,7 +1177,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
expected = [
|
expected = [
|
||||||
{"amount": 2.00, "receiver": "fred", "ower": "p\xe9p\xe9"},
|
{"amount": 2.00, "receiver": "fred", "ower": "p\xe9p\xe9"},
|
||||||
{"amount": 55.34, "receiver": "fred", "ower": "tata"},
|
{"amount": 55.34, "receiver": "fred", "ower": "tata"},
|
||||||
{"amount": 127.33, "receiver": "fred", "ower": "alexis"},
|
{"amount": 127.33, "receiver": "fred", "ower": "zorglub"},
|
||||||
]
|
]
|
||||||
|
|
||||||
self.assertEqual(json.loads(resp.data.decode("utf-8")), expected)
|
self.assertEqual(json.loads(resp.data.decode("utf-8")), expected)
|
||||||
|
@ -1199,7 +1189,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"amount,receiver,ower",
|
"amount,receiver,ower",
|
||||||
"2.0,fred,pépé",
|
"2.0,fred,pépé",
|
||||||
"55.34,fred,tata",
|
"55.34,fred,tata",
|
||||||
"127.33,fred,alexis",
|
"127.33,fred,zorglub",
|
||||||
]
|
]
|
||||||
received_lines = resp.data.decode("utf-8").split("\n")
|
received_lines = resp.data.decode("utf-8").split("\n")
|
||||||
|
|
||||||
|
@ -1235,15 +1225,15 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"amount": 200.0,
|
"amount": 200.0,
|
||||||
"payer_name": "fred",
|
"payer_name": "fred",
|
||||||
"payer_weight": 1.0,
|
"payer_weight": 1.0,
|
||||||
"owers": ["alexis", "tata"],
|
"owers": ["zorglub", "tata"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"date": "2016-12-31",
|
"date": "2016-12-31",
|
||||||
"what": "fromage a raclette",
|
"what": "fromage a raclette",
|
||||||
"amount": 10.0,
|
"amount": 10.0,
|
||||||
"payer_name": "alexis",
|
"payer_name": "zorglub",
|
||||||
"payer_weight": 2.0,
|
"payer_weight": 2.0,
|
||||||
"owers": ["alexis", "fred", "tata", "pepe"],
|
"owers": ["zorglub", "fred", "tata", "pepe"],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1291,7 +1281,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
|
|
||||||
project = models.Project.query.get("raclette")
|
project = models.Project.query.get("raclette")
|
||||||
|
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis", "weight": 2})
|
self.client.post("/raclette/members/add", data={"name": "zorglub", "weight": 2})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
self.client.post(
|
self.client.post(
|
||||||
|
@ -1320,15 +1310,15 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"amount": 200.0,
|
"amount": 200.0,
|
||||||
"payer_name": "fred",
|
"payer_name": "fred",
|
||||||
"payer_weight": 1.0,
|
"payer_weight": 1.0,
|
||||||
"owers": ["alexis", "tata"],
|
"owers": ["zorglub", "tata"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"date": "2016-12-31",
|
"date": "2016-12-31",
|
||||||
"what": "fromage a raclette",
|
"what": "fromage a raclette",
|
||||||
"amount": 10.0,
|
"amount": 10.0,
|
||||||
"payer_name": "alexis",
|
"payer_name": "zorglub",
|
||||||
"payer_weight": 2.0,
|
"payer_weight": 2.0,
|
||||||
"owers": ["alexis", "fred", "tata", "pepe"],
|
"owers": ["zorglub", "fred", "tata", "pepe"],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1648,7 +1638,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
# add a member
|
# add a member
|
||||||
req = self.client.post(
|
req = self.client.post(
|
||||||
"/api/projects/raclette/members",
|
"/api/projects/raclette/members",
|
||||||
data={"name": "Alexis"},
|
data={"name": "Zorglub"},
|
||||||
headers=self.get_auth("raclette"),
|
headers=self.get_auth("raclette"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1667,7 +1657,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
# Try to add another member with the same name.
|
# Try to add another member with the same name.
|
||||||
req = self.client.post(
|
req = self.client.post(
|
||||||
"/api/projects/raclette/members",
|
"/api/projects/raclette/members",
|
||||||
data={"name": "Alexis"},
|
data={"name": "Zorglub"},
|
||||||
headers=self.get_auth("raclette"),
|
headers=self.get_auth("raclette"),
|
||||||
)
|
)
|
||||||
self.assertStatus(400, req)
|
self.assertStatus(400, req)
|
||||||
|
@ -1748,9 +1738,9 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
self.api_create("raclette")
|
self.api_create("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.api_add_member("raclette", "alexis")
|
self.api_add_member("raclette", "zorglub")
|
||||||
self.api_add_member("raclette", "fred")
|
self.api_add_member("raclette", "fred")
|
||||||
self.api_add_member("raclette", "arnaud")
|
self.api_add_member("raclette", "quentin")
|
||||||
|
|
||||||
# get the list of bills (should be empty)
|
# get the list of bills (should be empty)
|
||||||
req = self.client.get(
|
req = self.client.get(
|
||||||
|
@ -1789,7 +1779,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"what": "fromage",
|
"what": "fromage",
|
||||||
"payer_id": 1,
|
"payer_id": 1,
|
||||||
"owers": [
|
"owers": [
|
||||||
{"activated": True, "id": 1, "name": "alexis", "weight": 1},
|
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
|
||||||
{"activated": True, "id": 2, "name": "fred", "weight": 1},
|
{"activated": True, "id": 2, "name": "fred", "weight": 1},
|
||||||
],
|
],
|
||||||
"amount": 25.0,
|
"amount": 25.0,
|
||||||
|
@ -1860,7 +1850,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"what": "beer",
|
"what": "beer",
|
||||||
"payer_id": 2,
|
"payer_id": 2,
|
||||||
"owers": [
|
"owers": [
|
||||||
{"activated": True, "id": 1, "name": "alexis", "weight": 1},
|
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
|
||||||
{"activated": True, "id": 2, "name": "fred", "weight": 1},
|
{"activated": True, "id": 2, "name": "fred", "weight": 1},
|
||||||
],
|
],
|
||||||
"amount": 25.0,
|
"amount": 25.0,
|
||||||
|
@ -1896,7 +1886,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
self.api_create("raclette")
|
self.api_create("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.api_add_member("raclette", "alexis")
|
self.api_add_member("raclette", "zorglub")
|
||||||
self.api_add_member("raclette", "fred")
|
self.api_add_member("raclette", "fred")
|
||||||
|
|
||||||
# valid amounts
|
# valid amounts
|
||||||
|
@ -1938,7 +1928,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"what": "fromage",
|
"what": "fromage",
|
||||||
"payer_id": 1,
|
"payer_id": 1,
|
||||||
"owers": [
|
"owers": [
|
||||||
{"activated": True, "id": 1, "name": "alexis", "weight": 1},
|
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
|
||||||
{"activated": True, "id": 2, "name": "fred", "weight": 1},
|
{"activated": True, "id": 2, "name": "fred", "weight": 1},
|
||||||
],
|
],
|
||||||
"amount": expected_amount,
|
"amount": expected_amount,
|
||||||
|
@ -1985,7 +1975,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
self.api_create("raclette")
|
self.api_create("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.api_add_member("raclette", "alexis")
|
self.api_add_member("raclette", "zorglub")
|
||||||
self.api_add_member("raclette", "fred")
|
self.api_add_member("raclette", "fred")
|
||||||
|
|
||||||
# add a bill
|
# add a bill
|
||||||
|
@ -2013,7 +2003,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"member": {
|
"member": {
|
||||||
"activated": True,
|
"activated": True,
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "alexis",
|
"name": "zorglub",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
},
|
},
|
||||||
"paid": 25.0,
|
"paid": 25.0,
|
||||||
|
@ -2051,9 +2041,9 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
self.api_create("raclette")
|
self.api_create("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.api_add_member("raclette", "alexis")
|
self.api_add_member("raclette", "zorglub")
|
||||||
self.api_add_member("raclette", "freddy familly", 4)
|
self.api_add_member("raclette", "freddy familly", 4)
|
||||||
self.api_add_member("raclette", "arnaud")
|
self.api_add_member("raclette", "quentin")
|
||||||
|
|
||||||
# add a bill
|
# add a bill
|
||||||
req = self.client.post(
|
req = self.client.post(
|
||||||
|
@ -2082,7 +2072,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"what": "fromage",
|
"what": "fromage",
|
||||||
"payer_id": 1,
|
"payer_id": 1,
|
||||||
"owers": [
|
"owers": [
|
||||||
{"activated": True, "id": 1, "name": "alexis", "weight": 1},
|
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
|
||||||
{"activated": True, "id": 2, "name": "freddy familly", "weight": 4},
|
{"activated": True, "id": 2, "name": "freddy familly", "weight": 4},
|
||||||
],
|
],
|
||||||
"amount": 25.0,
|
"amount": 25.0,
|
||||||
|
@ -2110,7 +2100,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
{
|
{
|
||||||
"activated": True,
|
"activated": True,
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "alexis",
|
"name": "zorglub",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"balance": 20.0,
|
"balance": 20.0,
|
||||||
},
|
},
|
||||||
|
@ -2124,7 +2114,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
{
|
{
|
||||||
"activated": True,
|
"activated": True,
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"name": "arnaud",
|
"name": "quentin",
|
||||||
"weight": 1.0,
|
"weight": 1.0,
|
||||||
"balance": 0,
|
"balance": 0,
|
||||||
},
|
},
|
||||||
|
@ -2146,12 +2136,12 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
self.login("raclette")
|
self.login("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.api_add_member("raclette", "alexis")
|
self.api_add_member("raclette", "zorglub")
|
||||||
|
|
||||||
resp = self.client.get("/raclette/history", follow_redirects=True)
|
resp = self.client.get("/raclette/history", follow_redirects=True)
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
f"Participant {em_surround('alexis')} added", resp.data.decode("utf-8")
|
f"Participant {em_surround('zorglub')} added", resp.data.decode("utf-8")
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
f"Project {em_surround('raclette')} added", resp.data.decode("utf-8"),
|
f"Project {em_surround('raclette')} added", resp.data.decode("utf-8"),
|
||||||
|
@ -2216,11 +2206,11 @@ class ModelsTestCase(IhatemoneyTestCase):
|
||||||
self.post_project("raclette")
|
self.post_project("raclette")
|
||||||
|
|
||||||
# add members
|
# add members
|
||||||
self.client.post("/raclette/members/add", data={"name": "alexis", "weight": 2})
|
self.client.post("/raclette/members/add", data={"name": "zorglub", "weight": 2})
|
||||||
self.client.post("/raclette/members/add", data={"name": "fred"})
|
self.client.post("/raclette/members/add", data={"name": "fred"})
|
||||||
self.client.post("/raclette/members/add", data={"name": "tata"})
|
self.client.post("/raclette/members/add", data={"name": "tata"})
|
||||||
# Add a member with a balance=0 :
|
# Add a member with a balance=0 :
|
||||||
self.client.post("/raclette/members/add", data={"name": "toto"})
|
self.client.post("/raclette/members/add", data={"name": "pépé"})
|
||||||
|
|
||||||
# create bills
|
# create bills
|
||||||
self.client.post(
|
self.client.post(
|
||||||
|
@ -2257,11 +2247,11 @@ class ModelsTestCase(IhatemoneyTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
project = models.Project.query.get_by_name(name="raclette")
|
project = models.Project.query.get_by_name(name="raclette")
|
||||||
alexis = models.Person.query.get_by_name(name="alexis", project=project)
|
zorglub = models.Person.query.get_by_name(name="zorglub", project=project)
|
||||||
alexis_bills = models.Bill.query.options(
|
zorglub_bills = models.Bill.query.options(
|
||||||
orm.subqueryload(models.Bill.owers)
|
orm.subqueryload(models.Bill.owers)
|
||||||
).filter(models.Bill.owers.contains(alexis))
|
).filter(models.Bill.owers.contains(zorglub))
|
||||||
for bill in alexis_bills.all():
|
for bill in zorglub_bills.all():
|
||||||
if bill.what == "red wine":
|
if bill.what == "red wine":
|
||||||
pay_each_expected = 20 / 2
|
pay_each_expected = 20 / 2
|
||||||
self.assertEqual(bill.pay_each(), pay_each_expected)
|
self.assertEqual(bill.pay_each(), pay_each_expected)
|
||||||
|
@ -2466,7 +2456,7 @@ class HistoryTestCase(IhatemoneyTestCase):
|
||||||
|
|
||||||
# adds a member to this project
|
# adds a member to this project
|
||||||
resp = self.client.post(
|
resp = self.client.post(
|
||||||
"/demo/members/add", data={"name": "alexis"}, follow_redirects=True
|
"/demo/members/add", data={"name": "zorglub"}, follow_redirects=True
|
||||||
)
|
)
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
|
@ -2602,14 +2592,14 @@ class HistoryTestCase(IhatemoneyTestCase):
|
||||||
def test_logs_for_common_actions(self):
|
def test_logs_for_common_actions(self):
|
||||||
# adds a member to this project
|
# adds a member to this project
|
||||||
resp = self.client.post(
|
resp = self.client.post(
|
||||||
"/demo/members/add", data={"name": "alexis"}, follow_redirects=True
|
"/demo/members/add", data={"name": "zorglub"}, follow_redirects=True
|
||||||
)
|
)
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
|
||||||
resp = self.client.get("/demo/history")
|
resp = self.client.get("/demo/history")
|
||||||
self.assertEqual(resp.status_code, 200)
|
self.assertEqual(resp.status_code, 200)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
f"Participant {em_surround('alexis')} added", resp.data.decode("utf-8")
|
f"Participant {em_surround('zorglub')} added", resp.data.decode("utf-8")
|
||||||
)
|
)
|
||||||
|
|
||||||
# create a bill
|
# create a bill
|
||||||
|
@ -2698,19 +2688,19 @@ class HistoryTestCase(IhatemoneyTestCase):
|
||||||
resp.data.decode("utf-8"),
|
resp.data.decode("utf-8"),
|
||||||
r"Participant %s:\s* Weight changed\s* from %s\s* to %s"
|
r"Participant %s:\s* Weight changed\s* from %s\s* to %s"
|
||||||
% (
|
% (
|
||||||
em_surround("alexis", regex_escape=True),
|
em_surround("zorglub", regex_escape=True),
|
||||||
em_surround("1.0", regex_escape=True),
|
em_surround("1.0", regex_escape=True),
|
||||||
em_surround("2.0", regex_escape=True),
|
em_surround("2.0", regex_escape=True),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"Participant %s renamed to %s"
|
"Participant %s renamed to %s"
|
||||||
% (em_surround("alexis"), em_surround("new name"),),
|
% (em_surround("zorglub"), em_surround("new name"),),
|
||||||
resp.data.decode("utf-8"),
|
resp.data.decode("utf-8"),
|
||||||
)
|
)
|
||||||
self.assertLess(
|
self.assertLess(
|
||||||
resp.data.decode("utf-8").index(
|
resp.data.decode("utf-8").index(
|
||||||
f"Participant {em_surround('alexis')} renamed"
|
f"Participant {em_surround('zorglub')} renamed"
|
||||||
),
|
),
|
||||||
resp.data.decode("utf-8").index("Weight changed"),
|
resp.data.decode("utf-8").index("Weight changed"),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue