Show the kiosk label prefix, and let a plugin declare the settings it owns
This commit is contained in:
148
tests/test_core/test_settings_plugin_declared.py
Normal file
148
tests/test_core/test_settings_plugin_declared.py
Normal file
@@ -0,0 +1,148 @@
|
||||
"""Tests for plugin-declared settings (contract 0.16.0).
|
||||
|
||||
Three regressions are pinned here, all found on the 3D-parts kiosk label
|
||||
prefix:
|
||||
|
||||
1. The kiosk runs logged out, so a setting it renders must be readable by an
|
||||
anonymous caller when the owning plugin declares it public - and only then.
|
||||
2. A save that creates the row for the first time must file it under the
|
||||
declared category, or the plugin's own settings page (which lists by
|
||||
category) stops seeing the value and the save looks lost.
|
||||
3. Settings declared by a later plugin version must reach a site that installed
|
||||
an earlier one; on_install/on_enable fire only on a state transition, so the
|
||||
upgrade pass has to seed them.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from shopdb.core.models import Setting
|
||||
|
||||
KIOSK_KEY = 'printedparts_label_prefix'
|
||||
PRIVATE_KEY = 'printedparts_alert_email'
|
||||
|
||||
|
||||
def _plugin(app, name='printedparts'):
|
||||
pm = app.extensions.get('plugin_manager')
|
||||
plugin = pm.loader.get_loaded_plugin(name) if pm else None
|
||||
if plugin is None:
|
||||
pytest.skip(f'{name} plugin not loaded in this build')
|
||||
return pm, plugin
|
||||
|
||||
|
||||
def test_plugin_declares_the_kiosk_prefix_public(app):
|
||||
_, plugin = _plugin(app)
|
||||
declared = {entry['key']: entry for entry in plugin.get_settings_defaults()}
|
||||
assert declared[KIOSK_KEY]['public'] is True
|
||||
assert declared[KIOSK_KEY]['category'] == 'printedparts'
|
||||
# Everything else the plugin owns stays behind auth.
|
||||
assert not any(entry.get('public') for key, entry in declared.items()
|
||||
if key != KIOSK_KEY)
|
||||
|
||||
|
||||
def test_anon_can_read_a_public_plugin_setting(client, db):
|
||||
"""The kiosk reads this with no token; a 404 leaves the prefix blank."""
|
||||
Setting.set(KIOSK_KEY, 'WJ', valuetype='string', category='printedparts')
|
||||
|
||||
resp = client.get(f'/api/settings/{KIOSK_KEY}')
|
||||
|
||||
assert resp.status_code == 200, resp.get_json()
|
||||
assert resp.get_json()['data']['value'] == 'WJ'
|
||||
|
||||
|
||||
def test_anon_cannot_read_a_nonpublic_plugin_setting(client, db):
|
||||
Setting.set(PRIVATE_KEY, 'lead@example.com', valuetype='string',
|
||||
category='printedparts')
|
||||
|
||||
resp = client.get(f'/api/settings/{PRIVATE_KEY}')
|
||||
|
||||
assert resp.status_code == 404
|
||||
body = resp.get_data(as_text=True)
|
||||
assert 'lead@example.com' not in body
|
||||
|
||||
|
||||
def test_anon_list_includes_public_plugin_settings_only(client, db):
|
||||
Setting.set(KIOSK_KEY, 'WJ', valuetype='string', category='printedparts')
|
||||
Setting.set(PRIVATE_KEY, 'lead@example.com', valuetype='string',
|
||||
category='printedparts')
|
||||
|
||||
resp = client.get('/api/settings?category=printedparts')
|
||||
|
||||
assert resp.status_code == 200
|
||||
keys = {row['key'] for row in resp.get_json()['data']}
|
||||
assert keys == {KIOSK_KEY}
|
||||
|
||||
|
||||
def test_first_save_files_the_key_under_its_declared_category(client, db,
|
||||
auth_headers):
|
||||
"""Save then reload, the way the settings page does it.
|
||||
|
||||
The row does not exist yet (the site installed before the key was added),
|
||||
so the PUT creates it. Filed under a placeholder category it would vanish
|
||||
from the page's category-filtered reload - the "it does not save" bug.
|
||||
"""
|
||||
assert Setting.query.filter_by(key=KIOSK_KEY).first() is None
|
||||
|
||||
resp = client.put(f'/api/settings/{KIOSK_KEY}', json={'value': 'WJ'},
|
||||
headers=auth_headers)
|
||||
assert resp.status_code == 200, resp.get_json()
|
||||
|
||||
setting = Setting.query.filter_by(key=KIOSK_KEY).first()
|
||||
assert setting.category == 'printedparts'
|
||||
|
||||
reload = client.get('/api/settings?category=printedparts',
|
||||
headers=auth_headers)
|
||||
values = {row['key']: row['value'] for row in reload.get_json()['data']}
|
||||
assert values[KIOSK_KEY] == 'WJ'
|
||||
|
||||
|
||||
def test_first_save_of_a_core_key_keeps_its_core_category(client, db,
|
||||
auth_headers):
|
||||
resp = client.put('/api/settings/facility_name',
|
||||
json={'value': 'Test Plant'}, headers=auth_headers)
|
||||
assert resp.status_code == 200, resp.get_json()
|
||||
|
||||
assert Setting.query.filter_by(key='facility_name').first().category == 'site'
|
||||
|
||||
|
||||
def test_undeclared_key_still_upserts(client, db, auth_headers):
|
||||
"""An ad-hoc key nobody declares keeps the old placeholder behavior."""
|
||||
resp = client.put('/api/settings/some_adhoc_key', json={'value': 'x'},
|
||||
headers=auth_headers)
|
||||
|
||||
assert resp.status_code == 200, resp.get_json()
|
||||
assert Setting.query.filter_by(key='some_adhoc_key').first().category == 'plugin'
|
||||
|
||||
|
||||
def test_upgrade_seeds_settings_missing_from_an_existing_site(app, db):
|
||||
"""`flask plugin upgrade-all` reaches a site that installed earlier."""
|
||||
pm, _ = _plugin(app)
|
||||
assert Setting.query.filter_by(key=KIOSK_KEY).first() is None
|
||||
|
||||
pm.sync_all_plugin_settings()
|
||||
|
||||
setting = Setting.query.filter_by(key=KIOSK_KEY).first()
|
||||
assert setting is not None
|
||||
assert setting.category == 'printedparts'
|
||||
assert setting.value == ''
|
||||
|
||||
|
||||
def test_sync_never_overwrites_a_configured_value(app, db):
|
||||
pm, _ = _plugin(app)
|
||||
Setting.set(KIOSK_KEY, 'WJ', valuetype='string', category='printedparts')
|
||||
|
||||
pm.sync_all_plugin_settings()
|
||||
|
||||
assert Setting.query.filter_by(key=KIOSK_KEY).first().value == 'WJ'
|
||||
|
||||
|
||||
def test_sync_rehomes_a_row_left_in_the_placeholder_category(app, db):
|
||||
"""Repairs rows an earlier save created before the key was declared."""
|
||||
pm, _ = _plugin(app)
|
||||
Setting.set(PRIVATE_KEY, 'lead@example.com', valuetype='string',
|
||||
category='plugin')
|
||||
|
||||
pm.sync_all_plugin_settings()
|
||||
|
||||
setting = Setting.query.filter_by(key=PRIVATE_KEY).first()
|
||||
assert setting.category == 'printedparts'
|
||||
assert setting.value == 'lead@example.com'
|
||||
Reference in New Issue
Block a user