diff --git a/py/routes/handlers/model_handlers.py b/py/routes/handlers/model_handlers.py index a20e0c4c..1fc8cf31 100644 --- a/py/routes/handlers/model_handlers.py +++ b/py/routes/handlers/model_handlers.py @@ -64,7 +64,6 @@ class ModelPageView: self._settings = settings_service self._server_i18n = server_i18n self._logger = logger - self._app_version = self._get_app_version() def _load_supporters(self) -> dict: """Load supporters data from JSON file.""" @@ -155,7 +154,7 @@ class ModelPageView: "request": request, "folders": [], "t": self._server_i18n.get_translation, - "version": self._app_version, + "version": self._get_app_version(), } if not is_initializing: diff --git a/static/js/managers/DoctorManager.js b/static/js/managers/DoctorManager.js index bf295199..81ee851d 100644 --- a/static/js/managers/DoctorManager.js +++ b/static/js/managers/DoctorManager.js @@ -103,6 +103,16 @@ export class DoctorManager { return document.body?.dataset?.appVersion || ''; } + buildReloadUrl() { + const url = new URL(window.location.href); + url.searchParams.set('_lm_reload', Date.now().toString()); + return url.toString(); + } + + reloadUi() { + window.location.replace(this.buildReloadUrl()); + } + setLoading(isLoading) { if (this.loadingState) { this.loadingState.classList.toggle('visible', isLoading); @@ -308,7 +318,7 @@ export class DoctorManager { await this.repairCache(); break; case 'reload-page': - window.location.reload(); + this.reloadUi(); break; default: break; diff --git a/tests/frontend/managers/DoctorManager.test.js b/tests/frontend/managers/DoctorManager.test.js index eb8c0ee0..aaffd48e 100644 --- a/tests/frontend/managers/DoctorManager.test.js +++ b/tests/frontend/managers/DoctorManager.test.js @@ -53,4 +53,26 @@ describe('DoctorManager', () => { expect(refreshSpy).not.toHaveBeenCalled(); }); + + it('builds a cache-busted reload URL that preserves the current location', () => { + renderDoctorFixture(); + window.history.replaceState({}, '', '/loras?filter=active#details'); + vi.spyOn(Date, 'now').mockReturnValue(1234567890); + + const manager = new DoctorManager(); + + const url = manager.buildReloadUrl(); + + expect(url).toBe('http://localhost:3000/loras?filter=active&_lm_reload=1234567890#details'); + }); + + it('delegates reload-page actions to reloadUi', async () => { + renderDoctorFixture(); + const manager = new DoctorManager(); + const reloadSpy = vi.spyOn(manager, 'reloadUi').mockImplementation(() => undefined); + + await manager.handleAction('reload-page'); + + expect(reloadSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/tests/routes/test_model_page_view.py b/tests/routes/test_model_page_view.py new file mode 100644 index 00000000..a9275c35 --- /dev/null +++ b/tests/routes/test_model_page_view.py @@ -0,0 +1,66 @@ +from __future__ import annotations + +from types import SimpleNamespace + +import jinja2 + +from py.routes.handlers.model_handlers import ModelPageView + + +class DummySettings: + def get(self, key, default=None): + return default + + +class DummyI18n: + def __init__(self): + self.locale = None + + def set_locale(self, locale): + self.locale = locale + + def get_translation(self, key, default=None, **_kwargs): + return default or key + + def create_template_filter(self): + return lambda key, *_args, **_kwargs: key + + +class DummyScanner: + def __init__(self): + self._cache = SimpleNamespace() + + async def get_cached_data(self, *_args, **_kwargs): + return SimpleNamespace(folders=[]) + + +class DummyService: + def __init__(self): + self.scanner = DummyScanner() + + +async def test_model_page_view_reads_version_per_request(): + template_env = jinja2.Environment( + loader=jinja2.DictLoader({"dummy.html": "{{ version }}"}), + autoescape=True, + ) + view = ModelPageView( + template_env=template_env, + template_name="dummy.html", + service=DummyService(), + settings_service=DummySettings(), + server_i18n=DummyI18n(), + logger=SimpleNamespace( + debug=lambda *_args, **_kwargs: None, + error=lambda *_args, **_kwargs: None, + ), + ) + + view._get_app_version = lambda: "1.0.2-old" + first = await view.handle(SimpleNamespace()) + + view._get_app_version = lambda: "1.0.2-new" + second = await view.handle(SimpleNamespace()) + + assert first.text == "1.0.2-old" + assert second.text == "1.0.2-new"