fix(tests): repair stale pins surfaced by the Phase 6 full-suite run
Two suite failures, neither caused by scanner code (the Phase 6 diff
touches no handler):
- search_test invalid_library_id expected the pre-family-lens 404;
7e586df4 shipped the AGENTS-mandated 403 for every out-of-set id
(existence must not be enumerable) and docs/contract_pins.md:195
documented it — this one subtest's expectation was missed. Pin
widened to the shipped 403.
- TestWebSocketPingPong deleted: it asserted a text-level ping→pong
exchange no server code has ever implemented and no client has ever
sent; it passed vacuously through its read-timeout path until
interleaved scan_progress broadcasts from the live server's scans
reached the socket first. Keepalive is the standard protocol-level
ping the hub already sends. Never-built behavior is not a pinnable
contract.
Both recorded in docs/contract_pins.md. Full container suite is green
except the documented pre-existing TestAdminCreateUser red.
This commit is contained in:
1 parent
2c5ad014c0
commit
6152137156
3 files changed
+37
-35
No files matched your search
@@ -413,10 +413,15 @@ func TestCollectionSearchLibraryFilter(t *testing.T) {
|
||||
shouldContain: book2ID,
|
||||
},
|
||||
{
|
||||
name: "invalid library_id",
|
||||
query: "Harry",
|
||||
libraryID: "00000000-0000-0000-0000-000000000000",
|
||||
expectedStatus: http.StatusNotFound,
|
||||
name: "invalid library_id",
|
||||
query: "Harry",
|
||||
libraryID: "00000000-0000-0000-0000-000000000000",
|
||||
// Family-lens standing rule (AGENTS.md): an explicit
|
||||
// library_id outside the visible set is a 403, never a
|
||||
// silent pass — and a nonexistent id is out-of-set too,
|
||||
// so existence is not enumerable. Behavior shipped in
|
||||
// 7e586df4 (Phase 1); this pin update was missed then.
|
||||
expectedStatus: http.StatusForbidden,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -157,37 +157,14 @@ func TestWebSocketProgressBroadcast(t *testing.T) {
|
||||
assert.Equal(t, "web", sourceDevice["type"])
|
||||
}
|
||||
|
||||
// TestWebSocketPingPong tests that ping/pong messages work correctly
|
||||
func TestWebSocketPingPong(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := setup.Token
|
||||
|
||||
wsURL := strings.Replace(setup.Server.URL, "http", "ws", 1) + "/ws/sync?token=" + token
|
||||
ws, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
|
||||
require.NoError(t, err)
|
||||
defer ws.Close()
|
||||
|
||||
// Read initial message
|
||||
ws.SetReadDeadline(time.Now().Add(5 * time.Second))
|
||||
_, _, _ = ws.ReadMessage()
|
||||
|
||||
// Send a ping message (as a text message for testing)
|
||||
err = ws.WriteMessage(websocket.TextMessage, []byte(`{"type":"ping"}`))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Server should respond with pong
|
||||
ws.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||
_, msg, err := ws.ReadMessage()
|
||||
if err == nil {
|
||||
var pongMsg map[string]interface{}
|
||||
err = json.Unmarshal(msg, &pongMsg)
|
||||
if err == nil {
|
||||
// Server might respond with pong
|
||||
assert.Equal(t, "pong", pongMsg["type"])
|
||||
}
|
||||
}
|
||||
}
|
||||
// TestWebSocketPingPong was deleted (2026-10-20, Phase 6 full-suite
|
||||
// repair): it asserted a TEXT-level {"type":"ping"} → {"type":"pong"}
|
||||
// exchange that no server code has ever implemented and no client
|
||||
// (web/src or Android) has ever sent — it passed vacuously through its
|
||||
// read-timeout path until interleaved scan_progress broadcasts started
|
||||
// failing the assert. Keepalive is the standard protocol-level ping the
|
||||
// hub already sends (websocket.go's ticker); if a text-level app ping
|
||||
// is ever wanted, build it server-side first, then re-pin it.
|
||||
|
||||
// TestWebSocketConnectionLimit tests that the server handles multiple connections
|
||||
func TestWebSocketConnectionLimit(t *testing.T) {
|
||||
|
||||
@@ -237,3 +237,23 @@ cover_image_path, has_conflict, format_group, badge`.
|
||||
- Watcher: a failed capability probe (one `Add` on a root folder)
|
||||
disables the watcher with ONE startup line instead of per-directory
|
||||
warning spam.
|
||||
|
||||
## 2026-10-20 — Stale pin repair (behavior shipped in 7e586df4)
|
||||
|
||||
- `GET /api/media-items/search` with an explicit `library_id` outside
|
||||
the requesting user's visible set — INCLUDING a nonexistent id —
|
||||
answers **403** (`library not accessible`), not 404. The family-lens
|
||||
standing rule (AGENTS.md) mandates 403 for every out-of-set id so
|
||||
library existence is not enumerable; Phase 1 (7e586df4) shipped it
|
||||
and documented it here, but the `invalid library_id` subtest in
|
||||
search_test.go still pinned the pre-family-lens 404. Pin widened to
|
||||
the shipped 403; no server change (discovered during the Phase 6
|
||||
full-suite run; the Phase 6 diff touches no handler code).
|
||||
- `TestWebSocketPingPong` DELETED: it asserted a text-level
|
||||
`{"type":"ping"}` → `{"type":"pong"}` exchange that no server code
|
||||
has ever implemented and no client (web/src, Android) has ever sent.
|
||||
It passed vacuously through its read-timeout path (deadline error
|
||||
skipped the asserts) until interleaved `scan_progress` broadcasts
|
||||
from the live server's scans started reaching the socket first.
|
||||
Keepalive is the standard protocol-level ping the hub already sends.
|
||||
Never-built behavior is not a pinnable contract.
|
||||
Reference in new issue
Block a user