mirror of
https://github.com/YunoHost-Apps/ihatemoney_ynh.git
synced 2024-09-03 19:26:15 +02:00
336 lines
12 KiB
Python
336 lines
12 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
|
|
|
|
return self.app.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)
|
|
|
|
# adding an user with the same name as another user from a different
|
|
# project should not cause any troubles
|
|
self.post_project("randomid")
|
|
self.login("randomid")
|
|
self.app.post("/randomid/members/add", data={'name': 'fred' })
|
|
self.assertEqual(
|
|
len(models.Project.query.get("randomid").active_members), 1)
|
|
|
|
|
|
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]))
|
|
|
|
def test_edit_project(self):
|
|
# A project should be editable
|
|
|
|
self.post_project("raclette")
|
|
new_data = {
|
|
'name': 'Super raclette party!',
|
|
'contact_email': 'alexis@notmyidea.org',
|
|
'password': 'didoudida'
|
|
}
|
|
|
|
resp = self.app.post("/raclette/edit", data=new_data,
|
|
follow_redirects=True)
|
|
self.assertEqual(resp.status_code, 200)
|
|
project = models.Project.query.get("raclette")
|
|
|
|
for key, value in new_data.items():
|
|
self.assertEqual(getattr(project, key), value, key)
|
|
|
|
# Editing a project with a wrong email address should fail
|
|
new_data['contact_email'] = 'wrong_email'
|
|
|
|
resp = self.app.post("/raclette/edit", data=new_data,
|
|
follow_redirects=True)
|
|
self.assertIn("Invalid email address", resp.data)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|