"""Tests for the shopfloor TV feed (/api/notifications/shopfloor). Since the notification-type display rework, per-employee fan-out is driven by the type's splitperemployee column (seeded true for Recognition/Training): a note naming several comma-joined SSOs yields one card per employee; types without the flag stay a single card. """ import pytest from plugins.notifications.models import Notification, NotificationType def _make_type(db, typename, typecolor, splitperemployee=False): t = NotificationType(typename=typename, typecolor=typecolor, splitperemployee=splitperemployee, isactive=True) db.session.add(t) db.session.commit() return t def _make_shopfloor_note(db, ntype, employeesso, employeename): n = Notification( notificationtypeid=ntype.notificationtypeid, notification='msg', businessunitid=None, isactive=True, isshopfloor=True, employeesso=employeesso, employeename=employeename, ) db.session.add(n) db.session.commit() return n @pytest.mark.parametrize('typecolor', ['recognition', 'training']) def test_multi_employee_split_into_one_card_each(client, db, typecolor): """A split-flagged note with two SSOs yields two current cards.""" ntype = _make_type(db, typecolor.capitalize(), typecolor, splitperemployee=True) _make_shopfloor_note(db, ntype, '111,222', 'Alice, Bob') resp = client.get('/api/notifications/shopfloor') assert resp.status_code == 200 current = resp.get_json()['data']['current'] assert len(current) == 2 assert {c['employeesso'] for c in current} == {'111', '222'} assert {c['employeename'] for c in current} == {'Alice', 'Bob'} def test_non_split_type_stays_single_card(client, db): """A type without splitperemployee is not fanned out, even with many SSOs.""" ntype = _make_type(db, 'Awareness', 'info') _make_shopfloor_note(db, ntype, '111,222', 'Alice, Bob') resp = client.get('/api/notifications/shopfloor') assert resp.status_code == 200 current = resp.get_json()['data']['current'] assert len(current) == 1 assert current[0]['employeesso'] == '111,222' def test_single_employee_recognition_stays_single_card(client, db): """One SSO produces one card (no spurious split on a lone employee).""" ntype = _make_type(db, 'Recognition', 'recognition', splitperemployee=True) _make_shopfloor_note(db, ntype, '111', 'Alice') resp = client.get('/api/notifications/shopfloor') assert resp.status_code == 200 current = resp.get_json()['data']['current'] assert len(current) == 1 assert current[0]['employeesso'] == '111' def test_shopfloor_names_resolve_live_when_not_stored(client, app, db): """A notification imported without employeename shows the directory name, not the bare SSO - single and split-per-employee paths both.""" from plugins.employees.models import DirectoryEmployee from plugins.notifications.models import Notification, NotificationType from shopdb.core.models import Setting with app.app_context(): Setting.set('employee_directory_mode', 'selfhosted', valuetype='string', category='employees') db.session.add(DirectoryEmployee( sso=502000777, firstname='Recert', lastname='Person')) ntype = NotificationType(typename='Recertification', typecolor='recertification', splitperemployee=True) db.session.add(ntype) db.session.flush() db.session.add(Notification( notificationtypeid=ntype.notificationtypeid, notification='Recert due', isshopfloor=True, employeesso='502000777', employeename=None)) db.session.commit() feed = client.get('/api/notifications/shopfloor').get_json()['data'] cards = feed['current'] + feed['upcoming'] card = next(c for c in cards if c['notification'] == 'Recert due') assert card['employeename'] == 'Recert Person'