Skip to content
Open
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
a9233ea
Migrate to Flask and Jinja templates.
jscheidtmann Jul 13, 2025
b229e76
Remove all logging not related to server.
jscheidtmann Jul 21, 2025
78c02b5
Add a few missing routes
jscheidtmann Jul 21, 2025
4095f94
Add obs_sessions.html template
jscheidtmann Jul 21, 2025
1d6ca76
Convert DMS <-> Decimal on clicking DMS checkbox
jscheidtmann Jul 22, 2025
717b000
Add jinja templates for locations, logs and tools. Fix gettext handli…
jscheidtmann Aug 23, 2025
6fd08af
Fix lint error: unused var babel
jscheidtmann Aug 23, 2025
c67ca53
First stab at translations
jscheidtmann Aug 23, 2025
adced99
extract i18n messages for webserver. German translation
jscheidtmann Aug 28, 2025
b575ccb
Update messages.po
laurentbourasseau Aug 28, 2025
6f61a12
few updates of German translation, that were off
jscheidtmann Aug 29, 2025
8a55c59
Update french translations
jscheidtmann Aug 29, 2025
6c404e9
compiled french translation
jscheidtmann Aug 29, 2025
34a273d
Bootstrapped spanish translation using LLM
jscheidtmann Aug 29, 2025
c2df6bf
Update messages.mo files.
jscheidtmann Aug 29, 2025
ec3d728
Fix lint message
jscheidtmann Aug 29, 2025
767a446
Fixed nox tests, run all nox sessions.
jscheidtmann Aug 29, 2025
bc58664
Update messages.po
laurentbourasseau Aug 29, 2025
db453d4
Add a first webserver test.
jscheidtmann Aug 29, 2025
f6c01d9
...
jscheidtmann Aug 29, 2025
51a0483
Merge branch 'jinja' of github.com:jscheidtmann/PiFinder into jinja
jscheidtmann Aug 31, 2025
27729e3
Selenium Tests added.
jscheidtmann Sep 1, 2025
e6744c0
Added more selenium tests.
jscheidtmann Sep 1, 2025
0f33110
Add details of selected target
jscheidtmann Sep 1, 2025
9a9a6bc
Add remote tests for up, down, left, right, and digits 0-9.
jscheidtmann Sep 2, 2025
fa3bf12
running nox formatting.
jscheidtmann Sep 2, 2025
87a7ef3
silence lint in test_web_remote
jscheidtmann Sep 2, 2025
a612dcb
Tested Marking Menus (sorting in objects list), LNG_LEFT, LNG_RIGHT.
jscheidtmann Sep 3, 2025
3921356
Added description to test_web_remote
jscheidtmann Sep 3, 2025
6a2c72c
Credit to Claude
jscheidtmann Sep 3, 2025
647f6b1
Test network page in webserver
jscheidtmann Sep 3, 2025
a02d440
Test webserver locations.
jscheidtmann Sep 4, 2025
f79dea9
Test webserver locations.
jscheidtmann Sep 4, 2025
9633c8f
Refactored helper functions into separate module.
jscheidtmann Sep 4, 2025
d8dae48
Ignore errors when shutting down Selenium WebDriver
jscheidtmann Sep 5, 2025
f85c2c5
Ran nox.
jscheidtmann Sep 5, 2025
6f243a5
Add webserver testing strategy to CLAUDE.md
jscheidtmann Sep 5, 2025
03d34ab
Testing webserver equipment page
jscheidtmann Sep 8, 2025
407835d
Add tests for observation list and details
jscheidtmann Sep 10, 2025
0364bab
In sys_utils_fake use backup and restore user data for testing
jscheidtmann Sep 10, 2025
64a47e0
Test for tools passing
jscheidtmann Sep 10, 2025
df356b0
Use headless testing
jscheidtmann Sep 10, 2025
3796291
Testing /tools page in webserver.
jscheidtmann Sep 10, 2025
109217a
Web tests running through. Ruff formatting
jscheidtmann Sep 11, 2025
e4f7bbd
Added smoke tests for important menu items.
jscheidtmann Sep 11, 2025
f85fd64
Refactor web login methods. Add PIFINDER_HOMEPAGE env variable
jscheidtmann Sep 11, 2025
9a08351
Add developer infos for running the web tests.
jscheidtmann Sep 11, 2025
c868bc6
Add warning to not run against a PiFinder in observational use.
jscheidtmann Sep 11, 2025
30d650f
PoC for mount control using Indi
jscheidtmann Sep 13, 2025
77d012b
Remove bottle dependency
jscheidtmann Sep 16, 2025
e797e39
Remove indi poc
jscheidtmann Sep 16, 2025
6d3dd24
Move fixtures to conftest.py
jscheidtmann Sep 16, 2025
b954043
Remove hardcoded urls to use get_homepage_url() instead
jscheidtmann Sep 16, 2025
3ecc8e9
Fix import of web_test_utils
jscheidtmann Sep 16, 2025
15c0df9
Add note that tests may occasionally fail.
jscheidtmann Sep 16, 2025
7766e4c
Ran nox
jscheidtmann Sep 16, 2025
73d08e7
Refactor: use consistent naming of keyboard keys.
jscheidtmann Sep 17, 2025
17b87f7
Merge branch 'main' into jinja
jscheidtmann Mar 5, 2026
6a5c099
Made tests green again in Chrome and Firefox
jscheidtmann Mar 5, 2026
ae57ca4
DevDocs: How to remove dangling shared memory. Add header for running…
jscheidtmann Mar 6, 2026
152be07
Web test suit runs (with a few skips) on Chrome & Safari (on Macbook …
jscheidtmann Mar 7, 2026
ad3e83f
Avoid calling delete_all_cookies()
jscheidtmann Mar 7, 2026
2fb94e2
Web tests: invoke delete_all_cookies only for a valid location. Neede…
jscheidtmann Mar 8, 2026
5edbeb4
Web tests green on all browsers (Safari, Chrome, Firefox)
jscheidtmann Mar 8, 2026
ce51dad
Tests: Added docstrings for web tests.
jscheidtmann Mar 9, 2026
817e794
Fix: Web Testing
jscheidtmann Mar 11, 2026
0aed527
web tests: Additional tests first version
jscheidtmann Mar 11, 2026
a57e023
More tests, green on Chrome
jscheidtmann Mar 16, 2026
583789c
Add necessity to run cedar-detect-server to CLAUDE.md
jscheidtmann Mar 16, 2026
8090879
mypy: Ignore conftest.py
jscheidtmann Mar 16, 2026
e812929
ruff formatting
jscheidtmann Mar 16, 2026
3211cfc
Merge branch 'main' into jinja
jscheidtmann Apr 18, 2026
e9e7aac
Use en as default language
jscheidtmann Apr 18, 2026
c45b3f4
Use waitress as wsgi server
jscheidtmann Apr 18, 2026
62da326
Merge branch 'main' into jinja
jscheidtmann Apr 19, 2026
cad65fc
Making sure eyepieces are always sorted
jscheidtmann Apr 19, 2026
ee81a2b
Migrated changed logs display and log configuration to server2.py
jscheidtmann Apr 21, 2026
470a0f1
Add ALT_SQUARE
jscheidtmann Apr 21, 2026
c11c132
Add import for i18n
jscheidtmann Apr 21, 2026
0f18fd6
menu changed: use correct location
jscheidtmann Apr 21, 2026
344b126
Recognize ALT_SQUARE
jscheidtmann Apr 22, 2026
ef8d532
Use minimal zip with expected path
jscheidtmann Apr 22, 2026
536e25b
Add tests directly testing the responses of web apis.
jscheidtmann Apr 22, 2026
610f40e
Tune down logs from webserver to Info and errors from flask subsysstems.
jscheidtmann Apr 22, 2026
b33b67d
Deleted old server and views, renamed server2 and views2
jscheidtmann Apr 22, 2026
fc722c4
Change references to "views"
jscheidtmann Apr 22, 2026
4ba398d
Use logging in config.py
jscheidtmann Apr 23, 2026
ca26136
Add --url parameter for webtests.
jscheidtmann Apr 23, 2026
d255ea2
Better handling for streaming logs.
jscheidtmann Apr 23, 2026
bb1f2ea
Use separate logger for handling and debugging of log stream and deac…
jscheidtmann Apr 23, 2026
a52a8e7
Wait for logs stream request to finish, before trying again.
jscheidtmann Apr 23, 2026
2ebd728
Reorder direct keyboard api calls
jscheidtmann Apr 23, 2026
013de3f
Test against PiFinder unit: Fixing tests
jscheidtmann Apr 23, 2026
ad7e560
Log each request.
jscheidtmann Apr 23, 2026
2515fe8
Fix german<->english language test, which switched to chinese and res…
jscheidtmann Apr 23, 2026
55fd905
Remove logging of requests
jscheidtmann Apr 23, 2026
26fce10
Poll for PiFinder unit to process all key presses.
jscheidtmann Apr 24, 2026
78c5a74
Describe locally running browsers, where web test suite is installed.
jscheidtmann Apr 24, 2026
085dc47
Tipps on running webtests on Safari
jscheidtmann Apr 24, 2026
9050535
Run nox and fixed error.
jscheidtmann Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Development Commands

**Running Python**
Developers may have created virtual environments in directories like ".venv" or "venv". Make sure these virtual
environments are activated before any of the python based tools below.

**Development workflow uses Nox for task automation:**
```bash
nox -s lint # Code linting with Ruff (auto-fixes issues)
Expand All @@ -12,6 +16,7 @@ nox -s type_hints # Type checking with MyPy
nox -s smoke_tests # Quick functionality validation
nox -s unit_tests # Full unit test suite
nox -s babel # I18n message extraction and compilation
nox -s web_tests # Testing the webserver, see below
```

**Direct testing with pytest:**
Expand All @@ -28,6 +33,8 @@ pip install -r requirements.txt
pip install -r requirements_dev.txt
```

Watch out for .venv directories containing virtual environments, that you need to activate first.

**Running the application:**
```bash
cd python/
Expand All @@ -44,13 +51,12 @@ python -m PiFinder.main [options]
- **GPS Process** - Location/time via GPSD or UBlox direct interface
- **IMU Process** - Motion tracking with BNO055 sensor
- **Integrator Process** - Combines solver + IMU data for real-time positioning
- **Web Server Process** - Web interface and SkySafari telescope control integration
- **Web Server Process** - Web interface and SkySafari integration as a telescope
- **Position Server Process** - External protocol support

**State Management:**
- `SharedStateObj` - Process-shared state using multiprocessing managers
- `UIState` - UI-specific state management
- Real-time synchronization of telescope position, GPS coordinates, and solved sky coordinates

**Database Layer:**
- SQLite backend (`astro_data/pifinder_objects.db`)
Expand All @@ -60,7 +66,7 @@ python -m PiFinder.main [options]

**Hardware Abstraction:**
- Camera interface supporting IMX296 (global shutter), IMX290/462, HQ cameras
- Display system for SSD1351 OLED and ST7789 LCD with red-light preservation
- Display system for SSD1351 OLED and ST7789 LCD with night vision preservation using red channel only
- Hardware keypad with PWM brightness control
- GPS integration via GPSD or direct UBlox protocol
- IMU sensor integration for motion detection and telescope orientation
Expand Down Expand Up @@ -99,6 +105,33 @@ Tests use pytest with custom markers for different test types. The smoke tests p
- Menu structure and navigation logic
- Multi-process logging and communication
- Hardware interface abstractions
- Website testing

### Website testing setup

**Testing Framework:** Uses Selenium WebDriver with Pytest for automated browser testing of the web interface

**Infrastructure Requirements:**
- Selenium Grid server at localhost:4444 (configurable via SELENIUM_GRID_URL environment variable).
This server is started outside of the test code, for maximum flexibility
- Chrome browser in headless mode for test execution
- Tests automatically skip if Selenium Grid is unavailable

**Test Coverage Areas:**
- **Web Interface** (`test_web_interface.py`): Basic page loading, image display, status table elements (Mode, coordinates, software version)
- **Location Management** (`test_web_locations.py`): Location CRUD operations, DMS coordinate entry, default switching, GPS integration via remote interface
- **Network Configuration** (`test_web_network.py`): WiFi settings form validation, network management, restart flows, modal dialogs
- **Remote Control** (`test_web_remote.py`): Authentication, virtual keypad, menu navigation, marking menus, API endpoint validation
- **Equipment Management** (`test_web_equipment.py`): Telescope and eyepiece CRUD operations, active equipment selection, form validation
- **Observation Tracking** (`test_web_observations.py`): Session list display, observation counters, detail pages, TSV export functionality

**Authentication:** All protected pages use default password "solveit"

**Responsive Testing:** Tests run on both desktop (1920x1080) and mobile (375x667) viewports

**API Integration:** Extensive use of `/api/current-selection` endpoint to validate UI state changes and ensure web interface accurately reflects PiFinder's internal state

**Helper Utilities:** Shared utilities in `web_test_utils.py` for login flows, key simulation, and state validation with recursive dictionary comparison

## Code Quality

Expand Down
58 changes: 57 additions & 1 deletion docs/source/dev_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,12 @@ The defined sessions are:
That means extracts strings to translate and updates the `.po`-files in `python/locale/**`
Then these are compiled into `.mo`-files. Unfortuntely, this changes the `.mo`-files in any case,
even if the there have been no changes to strings or their translation. As this will show up
as changes to checked-in, this is not run by default.
as changes to checked-in, this is not run by default.

- web_tests -> Runs PyTest and executes all tests marked as WEB. Web tests use Selenium
to automate browser testing of the PiFinder web interface. These tests require a
running Selenium Grid server and a running PiFinder web server. You can test against a real PiFinder
or a locally running instance. See the sections below for setup instructions.


CI/CD
Expand All @@ -330,6 +335,57 @@ your fork to run the existing automation to validate your code as you develop.

If you need help, reach out via email or discord. We are happy to help :-)

Website Tests
.............

The PiFinder web interface can be tested using automated browser tests powered by Selenium.
These tests verify functionality across different viewports (desktop and mobile) and ensure
the web interface works correctly.

The tests exercise the remote control features of PiFinder, changing **the state of the PiFinder** and
therefore should **not be run** against a PiFinder you are actively using for observing.

Running Website Tests
______________________________

To run the website tests needs a running Selenium Grid server and a running PiFinder web server.
You can test against a real PiFinder or a locally running instance.

Running against a locally running instance at localhost:8080:

.. code-block:: bash

cd ~/PiFinder/python
. .venv/bin/activate # Optionally active your virtual environment
export SELENIUM_GRID_URL=<your selenium grid url which ends in /wd/hub> # Optional, default is http://localhost:4444/wd/hub
nox -s web_tests

If you want to test against a real PiFinder, set the ``PIFINDER_HOMEPAGE`` environment variable to the URL of your PiFinder instance:

.. code-block:: bash

cd ~/PiFinder/python
. .venv/bin/activate # Optionally active your virtual environment
export SELENIUM_GRID_URL=<your selenium grid url which ends in /wd/hub> # Optional, default is http://localhost:4444/wd/hub
export PIFINDER_HOMEPAGE=http://pifinder.local # Change to the URL of your PiFinder, which needs to be in the same WiFi
nox -s web_tests

If you run the tests with-out a working Selenium Grid instance, the tests will all be skipped.
You can also run individual tests with PyTest directly, use ``SELENIUM_GRID_URL=... PIFINDER_HOMEPAGE=... pytest tests/webstite/test_file.py``.

Setting up Selenium Grid
___________________________

The website tests require a Selenium Grid server to run browser automation. The easiest way is to download the Selenum Grid server jar
from the selenium website, see https://www.selenium.dev/downloads/ and run it with Java:

.. code-block:: bash

java -jar selenium-server-<version>.jar standalone

The Selenium Grid server needs to run on the same machine where you have the browser installed, which you want to use for testing.
At the moment the tests will use Chrome.


Running/Debugging from the command line
---------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion python/PiFinder/gps_ubx_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ def _parse_nav_posecef(self, data: bytes) -> dict:
ecefZ = int.from_bytes(data[12:16], "little", signed=True) / 100.0
result = {}
if ecefX == 0 or ecefY == 0 or ecefZ == 0:
logging.debug(
logger.debug(
f"nav_posecef zeroes: ecefX: {ecefX}, ecefY: {ecefY}, ecefZ: {ecefZ}"
)
else:
Expand Down
6 changes: 3 additions & 3 deletions python/PiFinder/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from PiFinder import config
from PiFinder import pos_server
from PiFinder import utils
from PiFinder import server
from PiFinder import server2
from PiFinder import keyboard_interface

from PiFinder.multiproclogging import MultiprocLogging
Expand Down Expand Up @@ -364,7 +364,7 @@ def main(

server_process = Process(
name="Webserver",
target=server.run_server,
target=server2.run_server,
args=(
keyboard_queue,
ui_queue,
Expand Down Expand Up @@ -517,7 +517,7 @@ def main(
) # Only if new error is smaller
)
):
logger.info(
logger.debug(
f"Updating GPS location: new content: {gps_content}, old content: {location}"
)
location.lat = gps_content["lat"]
Expand Down
40 changes: 30 additions & 10 deletions python/PiFinder/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,18 @@ def __init__(
"B": self.ki.UP,
"C": self.ki.DOWN,
"D": self.ki.RIGHT,
"ALT_PLUS": self.ki.ALT_PLUS,
"ALT_MINUS": self.ki.ALT_MINUS,
"ALT_LEFT": self.ki.ALT_LEFT,
"ALT_UP": self.ki.ALT_UP,
"ALT_DOWN": self.ki.ALT_DOWN,
"ALT_RIGHT": self.ki.ALT_RIGHT,
"ALT_UP": self.ki.ALT_PLUS,
"ALT_DN": self.ki.ALT_MINUS,
"ALT_A": self.ki.ALT_LEFT,
"ALT_B": self.ki.ALT_UP,
"ALT_C": self.ki.ALT_DOWN,
"ALT_D": self.ki.ALT_RIGHT,
"ALT_0": self.ki.ALT_0,
"LNG_LEFT": self.ki.LNG_LEFT,
"LNG_UP": self.ki.LNG_UP,
"LNG_DOWN": self.ki.LNG_DOWN,
"LNG_RIGHT": self.ki.LNG_RIGHT,
"ALT_SQUARE": self.ki.ALT_SQUARE,
"LNG_A": self.ki.LNG_LEFT,
"LNG_B": self.ki.LNG_UP,
"LNG_C": self.ki.LNG_DOWN,
"LNG_D": self.ki.LNG_RIGHT,
"LNG_SQUARE": self.ki.LNG_SQUARE,
}

Expand Down Expand Up @@ -916,6 +917,25 @@ def key_callback():
self.key_callback(int(button))
return {"message": "success"}

@app.route("/api/current-selection")
@auth_required
def current_selection():
"""
Returns information about the currently active UI item for testing purposes
"""
try:
ui_state_data = self.shared_state.current_ui_state()
if ui_state_data is None:
return {"error": "UI state not available"}

response.content_type = "application/json"
return ui_state_data

except Exception as e:
logger.error(f"Error getting current UI state: {e}")
response.content_type = "application/json"
return {"error": str(e)}

@app.route("/image")
def serve_pil_image():
empty_img = Image.new(
Expand Down
Loading
Loading