mirror of
https://github.com/YunoHost-Apps/ihatemoney_ynh.git
synced 2024-09-03 19:26:15 +02:00
ef353d643c
This allows to isolate some behavior in the context of the web application so the API and the web application can behave in different ways.
303 lines
10 KiB
Python
303 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
import os
|
|
import tempfile
|
|
import unittest
|
|
|
|
from flask import session
|
|
|
|
import run
|
|
import models
|
|
|
|
class TestCase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
run.app.config['TESTING'] = True
|
|
|
|
run.app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///memory"
|
|
run.app.config['CSRF_ENABLED'] = False # simplify the tests
|
|
self.app = run.app.test_client()
|
|
|
|
models.db.init_app(run.app)
|
|
run.mail.init_app(run.app)
|
|
|
|
models.db.app = run.app
|
|
models.db.create_all()
|
|
|
|
def tearDown(self):
|
|
# clean after testing
|
|
models.db.session.remove()
|
|
models.db.drop_all()
|
|
|
|
def login(self, project, password=None, test_client=None):
|
|
password = password or project
|
|
test_client = test_client or self.app
|
|
|
|
return test_client.post('/authenticate', data=dict(
|
|
id=project, password=password), follow_redirects=True)
|
|
|
|
def post_project(self, name):
|
|
"""Create a fake project"""
|
|
# create the project
|
|
self.app.post("/create", data={
|
|
'name': name,
|
|
'id': name,
|
|
'password': name,
|
|
'contact_email': '%s@notmyidea.org' % name
|
|
})
|
|
|
|
def create_project(self, name):
|
|
models.db.session.add(models.Project(id=name, name=unicode(name),
|
|
password=name, contact_email="%s@notmyidea.org" % name))
|
|
models.db.session.commit()
|
|
|
|
class BudgetTestCase(TestCase):
|
|
|
|
def test_notifications(self):
|
|
"""Test that the notifications are sent, and that email adresses
|
|
are checked properly.
|
|
"""
|
|
# sending a message to one person
|
|
with run.mail.record_messages() as outbox:
|
|
|
|
# create a project
|
|
self.login("raclette")
|
|
|
|
self.post_project("raclette")
|
|
self.app.post("/raclette/invite", data=
|
|
{"emails": 'alexis@notmyidea.org'})
|
|
|
|
self.assertEqual(len(outbox), 1)
|
|
self.assertEqual(outbox[0].recipients, ["alexis@notmyidea.org"])
|
|
|
|
# sending a message to multiple persons
|
|
with run.mail.record_messages() as outbox:
|
|
self.app.post("/raclette/invite", data=
|
|
{"emails": 'alexis@notmyidea.org, toto@notmyidea.org'})
|
|
|
|
# only one message is sent to multiple persons
|
|
self.assertEqual(len(outbox), 1)
|
|
self.assertEqual(outbox[0].recipients,
|
|
["alexis@notmyidea.org", "toto@notmyidea.org"])
|
|
|
|
# mail address checking
|
|
with run.mail.record_messages() as outbox:
|
|
response = self.app.post("/raclette/invite", data={"emails": "toto"})
|
|
self.assertEqual(len(outbox), 0) # no message sent
|
|
self.assertIn("The email toto is not valid", response.data)
|
|
|
|
# mixing good and wrong adresses shouldn't send any messages
|
|
with run.mail.record_messages() as outbox:
|
|
self.app.post("/raclette/invite", data=
|
|
{"emails": 'alexis@notmyidea.org, alexis'}) # not valid
|
|
|
|
# only one message is sent to multiple persons
|
|
self.assertEqual(len(outbox), 0)
|
|
|
|
|
|
def test_project_creation(self):
|
|
with run.app.test_client() as c:
|
|
|
|
# add a valid project
|
|
c.post("/create", data={
|
|
'name': 'The fabulous raclette party',
|
|
'id': 'raclette',
|
|
'password': 'party',
|
|
'contact_email': 'raclette@notmyidea.org'
|
|
})
|
|
|
|
# session is updated
|
|
self.assertEqual(session['raclette'], 'party')
|
|
|
|
# project is created
|
|
self.assertEqual(len(models.Project.query.all()), 1)
|
|
|
|
# Add a second project with the same id
|
|
models.Project.query.get('raclette')
|
|
|
|
result = c.post("/create", data={
|
|
'name': 'Another raclette party',
|
|
'id': 'raclette', #already used !
|
|
'password': 'party',
|
|
'contact_email': 'raclette@notmyidea.org'
|
|
})
|
|
|
|
# no new project added
|
|
self.assertEqual(len(models.Project.query.all()), 1)
|
|
|
|
def test_membership(self):
|
|
self.post_project("raclette")
|
|
self.login("raclette")
|
|
|
|
# adds a member to this project
|
|
self.app.post("/raclette/members/add", data={'name': 'alexis' })
|
|
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
|
|
|
# adds him twice
|
|
result = self.app.post("/raclette/members/add", data={'name': 'alexis' })
|
|
# should not accept him
|
|
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
|
|
|
# add fred
|
|
self.app.post("/raclette/members/add", data={'name': 'fred' })
|
|
self.assertEqual(len(models.Project.query.get("raclette").members), 2)
|
|
|
|
# check fred is present in the bills page
|
|
result = self.app.get("/raclette/")
|
|
self.assertIn("fred", result.data)
|
|
|
|
# remove fred
|
|
self.app.post("/raclette/members/%s/delete" %
|
|
models.Project.query.get("raclette").members[-1].id)
|
|
|
|
# as fred is not bound to any bill, he is removed
|
|
self.assertEqual(len(models.Project.query.get("raclette").members), 1)
|
|
|
|
# add fred again
|
|
self.app.post("/raclette/members/add", data={'name': 'fred' })
|
|
fred_id = models.Project.query.get("raclette").members[-1].id
|
|
|
|
# bound him to a bill
|
|
result = self.app.post("/raclette/add", data={
|
|
'date': '2011-08-10',
|
|
'what': u'fromage à raclette',
|
|
'payer': fred_id,
|
|
'payed_for': [fred_id,],
|
|
'amount': '25',
|
|
})
|
|
|
|
# remove fred
|
|
self.app.post("/raclette/members/%s/delete" % fred_id)
|
|
|
|
# he is still in the database, but is deactivated
|
|
self.assertEqual(len(models.Project.query.get("raclette").members), 2)
|
|
self.assertEqual(
|
|
len(models.Project.query.get("raclette").active_members), 1)
|
|
|
|
# as fred is now deactivated, check that he is not listed when adding
|
|
# a bill or displaying the balance
|
|
result = self.app.get("/raclette/")
|
|
self.assertNotIn("/raclette/members/%s/delete" % fred_id, result.data)
|
|
|
|
result = self.app.get("/raclette/add")
|
|
self.assertNotIn("fred", result.data)
|
|
|
|
# adding him again should reactivate him
|
|
self.app.post("/raclette/members/add", data={'name': 'fred' })
|
|
self.assertEqual(
|
|
len(models.Project.query.get("raclette").active_members), 2)
|
|
|
|
def test_demo(self):
|
|
# Test that it is possible to connect automatically by going onto /demo
|
|
with run.app.test_client() as c:
|
|
models.db.session.add(models.Project(id="demo", name=u"demonstration",
|
|
password="demo", contact_email="demo@notmyidea.org"))
|
|
models.db.session.commit()
|
|
c.get("/demo")
|
|
|
|
# session is updated
|
|
self.assertEqual(session['demo'], 'demo')
|
|
|
|
def test_demo(self):
|
|
# test that a demo project is created if none is defined
|
|
self.assertEqual([], models.Project.query.all())
|
|
self.app.get("/demo")
|
|
self.assertTrue(models.Project.query.get("demo") is not None)
|
|
|
|
def test_authentication(self):
|
|
# raclette that the login / logout process works
|
|
self.create_project("raclette")
|
|
|
|
# try to see the project while not being authenticated should redirect
|
|
# to the authentication page
|
|
resp = self.app.post("/raclette", follow_redirects=True)
|
|
self.assertIn("Authentication", resp.data)
|
|
|
|
# try to connect with wrong credentials should not work
|
|
with run.app.test_client() as c:
|
|
resp = c.post("/authenticate",
|
|
data={'id': 'raclette', 'password': 'nope'})
|
|
|
|
self.assertIn("Authentication", resp.data)
|
|
self.assertNotIn('raclette', session)
|
|
|
|
# try to connect with the right credentials should work
|
|
with run.app.test_client() as c:
|
|
resp = c.post("/authenticate",
|
|
data={'id': 'raclette', 'password': 'raclette'})
|
|
|
|
self.assertNotIn("Authentication", resp.data)
|
|
self.assertIn('raclette', session)
|
|
self.assertEqual(session['raclette'], 'raclette')
|
|
|
|
# logout should wipe the session out
|
|
c.get("/exit")
|
|
self.assertNotIn('raclette', session)
|
|
|
|
def test_manage_bills(self):
|
|
self.post_project("raclette")
|
|
|
|
# add two persons
|
|
self.app.post("/raclette/members/add", data={'name': 'alexis' })
|
|
self.app.post("/raclette/members/add", data={'name': 'fred' })
|
|
|
|
members_ids = [m.id for m in models.Project.query.get("raclette").members]
|
|
|
|
# create a bill
|
|
self.app.post("/raclette/add", data={
|
|
'date': '2011-08-10',
|
|
'what': u'fromage à raclette',
|
|
'payer': members_ids[0],
|
|
'payed_for': members_ids,
|
|
'amount': '25',
|
|
})
|
|
raclette = models.Project.query.get("raclette")
|
|
bill = models.Bill.query.one()
|
|
self.assertEqual(bill.amount, 25)
|
|
|
|
# edit the bill
|
|
resp = self.app.post("/raclette/edit/%s" % bill.id, data={
|
|
'date': '2011-08-10',
|
|
'what': u'fromage à raclette',
|
|
'payer': members_ids[0],
|
|
'payed_for': members_ids,
|
|
'amount': '10',
|
|
})
|
|
|
|
bill = models.Bill.query.one()
|
|
self.assertEqual(bill.amount, 10, "bill edition")
|
|
|
|
# delete the bill
|
|
self.app.get("/raclette/delete/%s" % bill.id)
|
|
self.assertEqual(0, len(models.Bill.query.all()), "bill deletion")
|
|
|
|
# test balance
|
|
self.app.post("/raclette/add", data={
|
|
'date': '2011-08-10',
|
|
'what': u'fromage à raclette',
|
|
'payer': members_ids[0],
|
|
'payed_for': members_ids,
|
|
'amount': '19',
|
|
})
|
|
|
|
self.app.post("/raclette/add", data={
|
|
'date': '2011-08-10',
|
|
'what': u'fromage à raclette',
|
|
'payer': members_ids[1],
|
|
'payed_for': members_ids[0],
|
|
'amount': '20',
|
|
})
|
|
|
|
self.app.post("/raclette/add", data={
|
|
'date': '2011-08-10',
|
|
'what': u'fromage à raclette',
|
|
'payer': members_ids[1],
|
|
'payed_for': members_ids,
|
|
'amount': '17',
|
|
})
|
|
|
|
balance = models.Project.query.get("raclette").get_balance()
|
|
self.assertEqual(set(balance.values()), set([19.0, -19.0]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|