"""Sub 7 smoke test — runs inside odoo-shell on entech.""" env = env from datetime import datetime, timedelta Param = env['ir.config_parameter'].sudo() Sensor = env['fp.tank.sensor'] Tank = env['fusion.plating.tank'] Reading = env['fp.tank.reading'] # ---- Field presence + helper ----------------------------------------- assert 'poll_interval_minutes' in Sensor._fields assert 'poll_interval_display' in Sensor._fields assert 'x_fc_default_poll_interval_minutes' in env['res.company']._fields print('[OK] Fields present') default = env.company.x_fc_default_poll_interval_minutes assert default == 30, f'default should be 30, got {default}' print(f'[OK] Company default polling = {default} min') # Pick any existing sensor any_sensor = Sensor.search([], limit=1) assert any_sensor assert any_sensor._fp_effective_poll_interval_minutes() == 30 print(f'[OK] Helper returns default for blank sensor') any_sensor.poll_interval_minutes = 5 any_sensor.invalidate_recordset() assert any_sensor._fp_effective_poll_interval_minutes() == 5 assert '(override)' in any_sensor.poll_interval_display print(f'[OK] Override respected: {any_sensor.poll_interval_display}') any_sensor.poll_interval_minutes = 0 any_sensor.invalidate_recordset() assert '(default)' in any_sensor.poll_interval_display print(f'[OK] Blank interval shows default: {any_sensor.poll_interval_display}') # ---- Seed the 25 tanks + 50 sensors via the hook ---------------------- TankAll = Tank.with_context(active_test=False) SensorAll = Sensor.with_context(active_test=False) tanks_before = TankAll.search_count([]) sensors_before = SensorAll.search_count([]) Param.set_param('fusion_plating_iot.seed_entech_tanks', '1') from odoo.addons.fusion_plating_iot.hooks import _seed_entech_tanks_and_sensors _seed_entech_tanks_and_sensors(env) tanks_after = TankAll.search_count([]) sensors_after = SensorAll.search_count([]) print(f'[OK] Seed ran. Tanks: {tanks_before} → {tanks_after} (+{tanks_after - tanks_before})') print(f'[OK] Seed ran. Sensors: {sensors_before} → {sensors_after} (+{sensors_after - sensors_before})') assert tanks_after - tanks_before == 25, 'expected +25 tanks' assert sensors_after - sensors_before == 50, 'expected +50 sensors' # Active / inactive breakdown small_active = TankAll.search_count([('code', 'like', 'SMALL-%'), ('active', '=', True)]) big_active = TankAll.search_count([('code', 'like', 'BIG-%'), ('active', '=', True)]) big_inactive = TankAll.search_count([('code', 'like', 'BIG-%'), ('active', '=', False)]) assert small_active == 5, f'expected 5 small active, got {small_active}' assert big_active == 10, f'expected 10 big active, got {big_active}' assert big_inactive == 10, f'expected 10 big inactive, got {big_inactive}' print(f'[OK] Active/Inactive split: small={small_active}, big_active={big_active}, big_inactive={big_inactive}') # Per-tank sensor counts sample = TankAll.search([('code', '=', 'BIG-01')], limit=1) sample_sensors = SensorAll.search([('tank_id', '=', sample.id)]) types = sample_sensors.mapped('parameter_id.parameter_type') assert 'temperature' in types and 'ph' in types print(f'[OK] Big Tank #1 has sensors for: {types}') # Idempotency — re-run seed, counts don't change _seed_entech_tanks_and_sensors(env) assert TankAll.search_count([]) == tanks_after, 'seed not idempotent (tanks)' assert SensorAll.search_count([]) == sensors_after, 'seed not idempotent (sensors)' print('[OK] Seed is idempotent') # ---- Rate-limit: simulate two readings too close together ----------- rate_sensor = Sensor.search([('code', '!=', False)], limit=1) if False else any_sensor rate_sensor.poll_interval_minutes = 30 rate_sensor.last_reading_at = datetime.now() - timedelta(minutes=5) # 5 min ago print(f'[OK] Setup: interval=30min, last_reading=5min ago') # The ingest controller does the rate-limit. Simulate its check here. effective = rate_sensor._fp_effective_poll_interval_minutes() elapsed = datetime.now() - rate_sensor.last_reading_at assert elapsed < timedelta(minutes=effective), 'rate-limit check should fire' print('[OK] Rate-limit condition holds — reading would be skipped') rate_sensor.last_reading_at = datetime.now() - timedelta(minutes=35) # 35 min ago elapsed = datetime.now() - rate_sensor.last_reading_at assert elapsed >= timedelta(minutes=effective), 'rate-limit should allow after interval' print('[OK] Post-interval condition holds — reading would be stored') env.cr.rollback() print('\n=== SUB 7 SMOKE PASS — all assertions held ===')