2017-06-21 07:08:28 +02:00
|
|
|
import json
|
2017-06-22 16:36:08 +02:00
|
|
|
from datetime import timedelta
|
2017-08-08 19:03:42 +02:00
|
|
|
from unittest import mock
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
from django.contrib.auth.models import AnonymousUser, Permission, User
|
|
|
|
from django.test import Client
|
2017-06-22 16:36:08 +02:00
|
|
|
from django.utils import timezone
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
from channels.channel import Group
|
|
|
|
from channels.test import ChannelTestCase, WSClient
|
|
|
|
|
|
|
|
from . import kfet_open, OpenKfet
|
|
|
|
from .consumers import OpenKfetConsumer
|
|
|
|
|
|
|
|
|
|
|
|
class OpenKfetTest(ChannelTestCase):
|
|
|
|
"""OpenKfet object unit-tests suite."""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.kfet_open = OpenKfet()
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
self.kfet_open.clear_cache()
|
|
|
|
|
|
|
|
def test_defaults(self):
|
|
|
|
"""Default values."""
|
|
|
|
self.assertFalse(self.kfet_open.raw_open)
|
|
|
|
self.assertIsNone(self.kfet_open.last_update)
|
|
|
|
self.assertFalse(self.kfet_open.force_close)
|
|
|
|
self.assertFalse(self.kfet_open.is_open)
|
|
|
|
|
|
|
|
def test_raw_open(self):
|
|
|
|
"""Get and set raw_open; last_update is renewed."""
|
|
|
|
for raw_open in [True, False]:
|
|
|
|
prev_update = self.kfet_open.last_update
|
|
|
|
self.kfet_open.raw_open = raw_open
|
|
|
|
self.assertEqual(raw_open, self.kfet_open.raw_open)
|
|
|
|
self.assertNotEqual(prev_update, self.kfet_open.last_update)
|
|
|
|
|
|
|
|
def test_force_close(self):
|
|
|
|
"""Get and set force_close."""
|
|
|
|
for force_close in [True, False]:
|
|
|
|
self.kfet_open.force_close = force_close
|
|
|
|
self.assertEqual(force_close, self.kfet_open.force_close)
|
|
|
|
|
|
|
|
def test_is_open(self):
|
|
|
|
"""If force_close is disabled, is_open is raw_open."""
|
|
|
|
self.kfet_open.force_close = False
|
|
|
|
for raw_open in [True, False]:
|
|
|
|
self.kfet_open.raw_open = raw_open
|
|
|
|
self.assertEqual(raw_open, self.kfet_open.is_open)
|
|
|
|
|
|
|
|
def test_is_open_force_close(self):
|
|
|
|
"""If force_close is enabled, is_open is False."""
|
|
|
|
self.kfet_open.force_close = True
|
|
|
|
for raw_open in [True, False]:
|
|
|
|
self.kfet_open.raw_open = raw_open
|
|
|
|
self.assertFalse(self.kfet_open.is_open)
|
|
|
|
|
2017-06-22 16:36:08 +02:00
|
|
|
def test_status(self):
|
|
|
|
# (raw_open, force_close, expected status, expected admin)
|
|
|
|
cases = [
|
|
|
|
(False, False, OpenKfet.CLOSED, OpenKfet.CLOSED),
|
|
|
|
(False, True, OpenKfet.CLOSED, OpenKfet.CLOSED),
|
|
|
|
(True, False, OpenKfet.OPENED, OpenKfet.OPENED),
|
|
|
|
(True, True, OpenKfet.CLOSED, OpenKfet.FAKE_CLOSED),
|
|
|
|
]
|
|
|
|
for raw_open, force_close, exp_stat, exp_adm_stat in cases:
|
|
|
|
self.kfet_open.raw_open = raw_open
|
|
|
|
self.kfet_open.force_close = force_close
|
|
|
|
self.assertEqual(exp_stat, self.kfet_open.status())
|
|
|
|
self.assertEqual(exp_adm_stat, self.kfet_open.admin_status())
|
|
|
|
|
|
|
|
def test_status_unknown(self):
|
|
|
|
self.kfet_open.raw_open = True
|
|
|
|
self.kfet_open._last_update = timezone.now() - timedelta(days=30)
|
|
|
|
self.assertEqual(OpenKfet.UNKNOWN, self.kfet_open.status())
|
|
|
|
|
2017-06-21 07:08:28 +02:00
|
|
|
def test_export_user(self):
|
|
|
|
"""Export is limited for an anonymous user."""
|
|
|
|
export = self.kfet_open.export(AnonymousUser())
|
|
|
|
self.assertSetEqual(
|
2017-06-22 16:36:08 +02:00
|
|
|
set(['status']),
|
2017-06-21 07:08:28 +02:00
|
|
|
set(export),
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_export_team(self):
|
|
|
|
"""Export all values for a team member."""
|
|
|
|
user = User.objects.create_user('team', '', 'team')
|
|
|
|
user.user_permissions.add(Permission.objects.get(codename='is_team'))
|
|
|
|
export = self.kfet_open.export(user)
|
|
|
|
self.assertSetEqual(
|
2017-06-22 16:36:08 +02:00
|
|
|
set(['status', 'admin_status', 'force_close']),
|
2017-06-21 07:08:28 +02:00
|
|
|
set(export),
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_send_ws(self):
|
|
|
|
Group('kfet.open.base').add('test.open.base')
|
|
|
|
Group('kfet.open.team').add('test.open.team')
|
|
|
|
|
|
|
|
self.kfet_open.send_ws()
|
|
|
|
|
|
|
|
recv_base = self.get_next_message('test.open.base', require=True)
|
|
|
|
base = json.loads(recv_base['text'])
|
|
|
|
self.assertSetEqual(
|
2017-06-22 16:36:08 +02:00
|
|
|
set(['status']),
|
2017-06-21 07:08:28 +02:00
|
|
|
set(base),
|
|
|
|
)
|
|
|
|
|
|
|
|
recv_admin = self.get_next_message('test.open.team', require=True)
|
|
|
|
admin = json.loads(recv_admin['text'])
|
|
|
|
self.assertSetEqual(
|
2017-06-22 16:36:08 +02:00
|
|
|
set(['status', 'admin_status', 'force_close']),
|
2017-06-21 07:08:28 +02:00
|
|
|
set(admin),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class OpenKfetViewsTest(ChannelTestCase):
|
|
|
|
"""OpenKfet views unit-tests suite."""
|
|
|
|
|
|
|
|
def setUp(self):
|
2017-08-08 19:03:42 +02:00
|
|
|
# Need this (and here) because of '<client>.login' in setUp
|
|
|
|
patcher_messages = mock.patch('gestioncof.signals.messages')
|
|
|
|
patcher_messages.start()
|
|
|
|
self.addCleanup(patcher_messages.stop)
|
|
|
|
|
2017-06-21 07:08:28 +02:00
|
|
|
# get some permissions
|
|
|
|
perms = {
|
|
|
|
'kfet.is_team': Permission.objects.get(codename='is_team'),
|
|
|
|
'kfet.can_force_close': Permission.objects.get(codename='can_force_close'),
|
|
|
|
}
|
|
|
|
|
|
|
|
# authenticated user and its client
|
|
|
|
self.u = User.objects.create_user('user', '', 'user')
|
|
|
|
self.c = Client()
|
|
|
|
self.c.login(username='user', password='user')
|
|
|
|
|
|
|
|
# team user and its clients
|
|
|
|
self.t = User.objects.create_user('team', '', 'team')
|
|
|
|
self.t.user_permissions.add(perms['kfet.is_team'])
|
|
|
|
self.c_t = Client()
|
|
|
|
self.c_t.login(username='team', password='team')
|
|
|
|
|
|
|
|
# admin user and its client
|
|
|
|
self.a = User.objects.create_user('admin', '', 'admin')
|
|
|
|
self.a.user_permissions.add(
|
|
|
|
perms['kfet.is_team'], perms['kfet.can_force_close'],
|
|
|
|
)
|
|
|
|
self.c_a = Client()
|
|
|
|
self.c_a.login(username='admin', password='admin')
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
kfet_open.clear_cache()
|
|
|
|
|
|
|
|
def test_door(self):
|
|
|
|
"""Edit raw_status."""
|
|
|
|
for sent, expected in [(1, True), (0, False)]:
|
2017-06-22 15:48:45 +02:00
|
|
|
resp = Client().post('/k-fet/open/raw_open', {
|
|
|
|
'raw_open': sent,
|
|
|
|
'token': 'plop',
|
|
|
|
})
|
2017-06-21 07:08:28 +02:00
|
|
|
self.assertEqual(200, resp.status_code)
|
|
|
|
self.assertEqual(expected, kfet_open.raw_open)
|
|
|
|
|
|
|
|
def test_force_close(self):
|
|
|
|
"""Edit force_close."""
|
|
|
|
for sent, expected in [(1, True), (0, False)]:
|
|
|
|
resp = self.c_a.post('/k-fet/open/force_close', {'force_close': sent})
|
|
|
|
self.assertEqual(200, resp.status_code)
|
|
|
|
self.assertEqual(expected, kfet_open.force_close)
|
|
|
|
|
|
|
|
def test_force_close_forbidden(self):
|
|
|
|
"""Can't edit force_close without kfet.can_force_close permission."""
|
|
|
|
clients = [Client(), self.c, self.c_t]
|
|
|
|
for client in clients:
|
|
|
|
resp = client.post('/k-fet/open/force_close', {'force_close': 0})
|
|
|
|
self.assertEqual(403, resp.status_code)
|
|
|
|
|
|
|
|
|
|
|
|
class OpenKfetConsumerTest(ChannelTestCase):
|
|
|
|
"""OpenKfet consumer unit-tests suite."""
|
|
|
|
|
|
|
|
def test_standard_user(self):
|
|
|
|
"""Lambda user is added to kfet.open.base group."""
|
|
|
|
# setup anonymous client
|
|
|
|
c = WSClient()
|
|
|
|
|
|
|
|
# connect
|
|
|
|
c.send_and_consume('websocket.connect', path='/ws/k-fet/open',
|
|
|
|
fail_on_none=True)
|
|
|
|
|
|
|
|
# initialization data is replied on connection
|
|
|
|
self.assertIsNotNone(c.receive())
|
|
|
|
|
|
|
|
# client belongs to the 'kfet.open' group...
|
|
|
|
OpenKfetConsumer.group_send('kfet.open.base', {'test': 'plop'})
|
|
|
|
self.assertEqual(c.receive(), {'test': 'plop'})
|
|
|
|
|
|
|
|
# ...but not to the 'kfet.open.admin' one
|
|
|
|
OpenKfetConsumer.group_send('kfet.open.team', {'test': 'plop'})
|
|
|
|
self.assertIsNone(c.receive())
|
|
|
|
|
2017-08-08 19:03:42 +02:00
|
|
|
@mock.patch('gestioncof.signals.messages')
|
|
|
|
def test_team_user(self, mock_messages):
|
2017-06-21 07:08:28 +02:00
|
|
|
"""Team user is added to kfet.open.team group."""
|
|
|
|
# setup team user and its client
|
|
|
|
t = User.objects.create_user('team', '', 'team')
|
|
|
|
t.user_permissions.add(
|
|
|
|
Permission.objects.get(codename='is_team')
|
|
|
|
)
|
|
|
|
c = WSClient()
|
|
|
|
c.force_login(t)
|
|
|
|
|
|
|
|
# connect
|
|
|
|
c.send_and_consume('websocket.connect', path='/ws/k-fet/open',
|
|
|
|
fail_on_none=True)
|
|
|
|
|
|
|
|
# initialization data is replied on connection
|
|
|
|
self.assertIsNotNone(c.receive())
|
|
|
|
|
|
|
|
# client belongs to the 'kfet.open.admin' group...
|
|
|
|
OpenKfetConsumer.group_send('kfet.open.team', {'test': 'plop'})
|
|
|
|
self.assertEqual(c.receive(), {'test': 'plop'})
|
|
|
|
|
|
|
|
# ... but not to the 'kfet.open' one
|
|
|
|
OpenKfetConsumer.group_send('kfet.open.base', {'test': 'plop'})
|
|
|
|
self.assertIsNone(c.receive())
|
|
|
|
|
|
|
|
|
|
|
|
class OpenKfetScenarioTest(ChannelTestCase):
|
|
|
|
"""OpenKfet functionnal tests suite."""
|
|
|
|
|
|
|
|
def setUp(self):
|
2017-08-08 19:03:42 +02:00
|
|
|
# Need this (and here) because of '<client>.login' in setUp
|
|
|
|
patcher_messages = mock.patch('gestioncof.signals.messages')
|
|
|
|
patcher_messages.start()
|
|
|
|
self.addCleanup(patcher_messages.stop)
|
|
|
|
|
2017-06-21 07:08:28 +02:00
|
|
|
# anonymous client (for views)
|
|
|
|
self.c = Client()
|
|
|
|
# anonymous client (for websockets)
|
|
|
|
self.c_ws = WSClient()
|
|
|
|
|
|
|
|
# root user
|
|
|
|
self.r = User.objects.create_superuser('root', '', 'root')
|
|
|
|
# its client (for views)
|
|
|
|
self.r_c = Client()
|
|
|
|
self.r_c.login(username='root', password='root')
|
|
|
|
# its client (for websockets)
|
|
|
|
self.r_c_ws = WSClient()
|
|
|
|
self.r_c_ws.force_login(self.r)
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
kfet_open.clear_cache()
|
|
|
|
|
|
|
|
def ws_connect(self, ws_client):
|
|
|
|
ws_client.send_and_consume(
|
|
|
|
'websocket.connect', path='/ws/k-fet/open',
|
|
|
|
fail_on_none=True,
|
|
|
|
)
|
|
|
|
return ws_client.receive(json=True)
|
|
|
|
|
|
|
|
def test_scenario_0(self):
|
|
|
|
"""Clients connect."""
|
|
|
|
# test for anonymous user
|
|
|
|
msg = self.ws_connect(self.c_ws)
|
|
|
|
self.assertSetEqual(
|
2017-06-22 16:36:08 +02:00
|
|
|
set(['status']),
|
2017-06-21 07:08:28 +02:00
|
|
|
set(msg),
|
|
|
|
)
|
|
|
|
|
|
|
|
# test for root user
|
|
|
|
msg = self.ws_connect(self.r_c_ws)
|
|
|
|
self.assertSetEqual(
|
2017-06-22 16:36:08 +02:00
|
|
|
set(['status', 'admin_status', 'force_close']),
|
2017-06-21 07:08:28 +02:00
|
|
|
set(msg),
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_scenario_1(self):
|
|
|
|
"""Clients connect, door opens, enable force close."""
|
|
|
|
self.ws_connect(self.c_ws)
|
|
|
|
self.ws_connect(self.r_c_ws)
|
|
|
|
|
|
|
|
# door sent "I'm open!"
|
2017-06-22 15:48:45 +02:00
|
|
|
self.c.post('/k-fet/open/raw_open', {
|
|
|
|
'raw_open': True,
|
|
|
|
'token': 'plop',
|
|
|
|
})
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
# anonymous user agree
|
|
|
|
msg = self.c_ws.receive(json=True)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.OPENED, msg['status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
# root user too
|
|
|
|
msg = self.r_c_ws.receive(json=True)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.OPENED, msg['status'])
|
|
|
|
self.assertEqual(OpenKfet.OPENED, msg['admin_status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
# admin says "no it's closed"
|
|
|
|
self.r_c.post('/k-fet/open/force_close', {'force_close': True})
|
|
|
|
|
|
|
|
# so anonymous user see it's closed
|
|
|
|
msg = self.c_ws.receive(json=True)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.CLOSED, msg['status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
# root user too
|
|
|
|
msg = self.r_c_ws.receive(json=True)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.CLOSED, msg['status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
# but root knows things
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.FAKE_CLOSED, msg['admin_status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
self.assertTrue(msg['force_close'])
|
|
|
|
|
|
|
|
def test_scenario_2(self):
|
|
|
|
"""Starting falsely closed, clients connect, disable force close."""
|
|
|
|
kfet_open.raw_open = True
|
|
|
|
kfet_open.force_close = True
|
|
|
|
|
|
|
|
msg = self.ws_connect(self.c_ws)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.CLOSED, msg['status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
msg = self.ws_connect(self.r_c_ws)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.CLOSED, msg['status'])
|
|
|
|
self.assertEqual(OpenKfet.FAKE_CLOSED, msg['admin_status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
self.assertTrue(msg['force_close'])
|
|
|
|
|
|
|
|
self.r_c.post('/k-fet/open/force_close', {'force_close': False})
|
|
|
|
|
|
|
|
msg = self.c_ws.receive(json=True)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.OPENED, msg['status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
msg = self.r_c_ws.receive(json=True)
|
2017-06-22 16:36:08 +02:00
|
|
|
self.assertEqual(OpenKfet.OPENED, msg['status'])
|
|
|
|
self.assertEqual(OpenKfet.OPENED, msg['admin_status'])
|
2017-06-21 07:08:28 +02:00
|
|
|
self.assertFalse(msg['force_close'])
|