fix(shopfloor): Phase D review findings — defensive cleanups + bootstrap test

Important I1: tablet_session_manager.beginSession() now calls
_removeListeners() (and clears any pending _tickHandle) defensively
at start. Prevents DOM listener leak on dev hot-reload or any path
that re-bootstraps without a clean endSession() first.

Important I2: tablet_lock._checkIdle() early-returns in session_swap
mode. The tablet_session_manager owns idle tracking there (5s poll,
calls /fp/tablet/lock_session directly). Was previously dormant by
accident because session_swap never populates the legacy techStore;
explicit guard makes the decoupling intentional.

Minor M5: session_swap unlock success now resets selectedTileUserId
before window.location.reload(), matching the legacy path''s
cleanup pattern. Cosmetic before reload kicks in.

Minor M9: New test_tiles_bootstrap_fields with 3 HttpCase tests
asserting /fp/tablet/tiles returns tablet_session_mode, kiosk_uid,
and current_uid. The OWL lock screen branches on all three — a
contract regression would silently break session_swap.

Minor M10: Added inline comment near _sessionModeCache declaration
in fp_rpc.js explaining the page-reload-invalidates-cache lifecycle.

Deferred (for future polish, NOT in this commit):
- I3 (_getSessionMode ACL gap for tech users — functionally correct,
  just suboptimal; cache fallback to ''legacy'' kicks in)
- M6 (wrapper component Hand-Off buttons no-op in session_swap)
- M7 (hardcoded idle/ceiling thresholds — server-configurable later)
- M8 (timer divergence vs activity_tracker — unify later)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-24 13:30:29 -04:00
parent 6d4b6284ad
commit 7ff46af192
5 changed files with 69 additions and 0 deletions

View File

@@ -8,3 +8,4 @@ from . import test_tablet_session_event_model
from . import test_tablet_pin_auth_manager
from . import test_unlock_lock_session_endpoints
from . import test_force_lock_cron
from . import test_tiles_bootstrap_fields

View File

@@ -0,0 +1,52 @@
from odoo.tests.common import HttpCase, tagged
@tagged('-at_install', 'post_install', 'fp_tablet')
class TestTilesBootstrapFields(HttpCase):
"""Phase D added 3 bootstrap fields to /fp/tablet/tiles:
tablet_session_mode, kiosk_uid, current_uid. The OWL lock screen
branches on these, so a contract regression would silently
break the session-swap flow."""
def setUp(self):
super().setUp()
# Ensure kiosk password exists so we can authenticate as kiosk.
ICP = self.env['ir.config_parameter'].sudo()
ICP.set_param('fp.tablet.kiosk_password', 'tiles_test_pwd')
kiosk = self.env.ref('fusion_plating_shopfloor.user_fp_tablet_kiosk')
kiosk.sudo().password = 'tiles_test_pwd'
self.kiosk = kiosk
def _jsonrpc(self, route, params):
import json
return self.url_open(
route,
data=json.dumps({'jsonrpc': '2.0', 'params': params}),
headers={'Content-Type': 'application/json'},
).json()
def test_tiles_returns_session_mode(self):
self.authenticate('fp_tablet_kiosk@enplating.local', 'tiles_test_pwd')
resp = self._jsonrpc('/fp/tablet/tiles', {})
result = resp.get('result', {})
self.assertIn('tablet_session_mode', result,
'tiles bootstrap must include tablet_session_mode for OWL branching')
# Default value is 'legacy' until rollout flips the flag
self.assertIn(result['tablet_session_mode'], ('legacy', 'session_swap'))
def test_tiles_returns_kiosk_uid(self):
self.authenticate('fp_tablet_kiosk@enplating.local', 'tiles_test_pwd')
resp = self._jsonrpc('/fp/tablet/tiles', {})
result = resp.get('result', {})
self.assertIn('kiosk_uid', result,
'tiles bootstrap must include kiosk_uid for OWL session detection')
self.assertEqual(result['kiosk_uid'], self.kiosk.id)
def test_tiles_returns_current_uid(self):
self.authenticate('fp_tablet_kiosk@enplating.local', 'tiles_test_pwd')
resp = self._jsonrpc('/fp/tablet/tiles', {})
result = resp.get('result', {})
self.assertIn('current_uid', result,
'tiles bootstrap must include current_uid so OWL can compare to kiosk_uid')
# When authenticated as kiosk, current_uid IS kiosk_uid
self.assertEqual(result['current_uid'], self.kiosk.id)