Files
shopdb-flask/tests/test_plugins/test_board_order.py
cproudlock 442a631557 Let a site choose the order its board rows run in
Rows ran in display-style order and then alphabetically, so what led the screen
was an accident of styling and the alphabet - a new type called Awareness
landed above Recertification for no better reason than the letter A.

Each type now carries a board position, lowest first, set on the Notification
Types page. The migration seeds Recognition at 10 and Recertification at 20 and
leaves everything else at 100, so an existing board keeps the order sites
already expect. Steps of ten leave room to slot a row in without renumbering
the rest.

A row shared by several types sits wherever its earliest-ordered type puts it,
so a category moves as a unit.
2026-08-08 14:20:35 -04:00

107 lines
4.1 KiB
Python

"""Tests for notificationtypes.boardorder (row order on the shopfloor board).
Rows used to run in display-style order and then alphabetically, so what led
the screen was an accident of styling and the alphabet. Each type now carries a
position, low first, and a shared category row sits wherever its
earliest-ordered type puts it.
The sort itself is frontend (ShopfloorDashboard.vue); pinned here is the
contract it sorts on - the feed carries boardorder per card, the type API
round-trips and validates it, and the migration seeds the shipped order.
"""
from plugins.notifications.models import Notification, NotificationType
def _make_type(db, typename, boardorder=100, displaystyle='grid', boardcategory=None):
t = NotificationType(typename=typename, typecolor='#17a2b8', isactive=True,
displaystyle=displaystyle, boardcategory=boardcategory,
boardorder=boardorder)
db.session.add(t)
db.session.commit()
return t
def _make_note(db, ntype, text):
n = Notification(notificationtypeid=ntype.notificationtypeid,
notification=text, businessunitid=None,
isactive=True, isshopfloor=True)
db.session.add(n)
db.session.commit()
return n
def _current(client):
resp = client.get('/api/notifications/shopfloor')
assert resp.status_code == 200, resp.get_json()
return resp.get_json()['data']['current']
def test_feed_carries_the_order_per_card(client, db):
ntype = _make_type(db, 'Recognition', boardorder=10)
_make_note(db, ntype, 'ten years')
assert _current(client)[0]['boardorder'] == 10
def test_a_type_defaults_to_the_back(client, db):
"""A new type lands behind the seeded rows rather than jumping the queue."""
ntype = NotificationType(typename='Fresh', typecolor='#17a2b8', isactive=True)
db.session.add(ntype)
db.session.commit()
assert ntype.boardorder == 100
def test_api_round_trips_the_order(client, db, auth_headers):
create = client.post('/api/notifications/types',
json={'typename': 'Awareness', 'boardorder': 30},
headers=auth_headers)
assert create.status_code in (200, 201), create.get_json()
typeid = create.get_json()['data']['notificationtypeid']
assert create.get_json()['data']['boardorder'] == 30
updated = client.put(f'/api/notifications/types/{typeid}',
json={'boardorder': 40}, headers=auth_headers)
assert updated.get_json()['data']['boardorder'] == 40
def test_api_rejects_a_nonsense_order(client, db, auth_headers):
resp = client.post('/api/notifications/types',
json={'typename': 'Bad', 'boardorder': 'first'},
headers=auth_headers)
assert resp.status_code == 400
assert 'boardorder' in resp.get_data(as_text=True)
def test_api_rejects_an_out_of_range_order(client, db, auth_headers):
resp = client.post('/api/notifications/types',
json={'typename': 'Bad', 'boardorder': 1000},
headers=auth_headers)
assert resp.status_code == 400
def test_order_change_moves_the_config_version(client, db, auth_headers):
"""Open kiosks reload on a layout change; a re-ordered board is one."""
ntype = _make_type(db, 'Awareness')
before = client.get('/api/notifications/shopfloor').get_json()['data']['configversion']
client.put(f'/api/notifications/types/{ntype.notificationtypeid}',
json={'boardorder': 30}, headers=auth_headers)
after = client.get('/api/notifications/shopfloor').get_json()['data']['configversion']
assert before != after
def test_types_in_one_category_can_carry_different_orders(client, db):
"""The row takes the lowest; the feed still reports each type's own."""
change = _make_type(db, 'Change', boardorder=30, boardcategory='Current Events')
incident = _make_type(db, 'Incident', boardorder=50, boardcategory='Current Events')
_make_note(db, change, 'retooling')
_make_note(db, incident, 'press down')
orders = {c['typename']: c['boardorder'] for c in _current(client)}
assert orders == {'Change': 30, 'Incident': 50}