feat(test): run live Hashview tests against a local docker stack

The live Hashview tests previously could only run against a remote server
configured in config.json, and the CLI ignored env-var overrides, so the
suite always hit prod. Prod runs an older Hashview whose /v1/jobs/add 500s
on a notify_email kwarg, which masked real client/server drift.

Wire the suite up to a local Hashview docker stack:

- main.py: HASHVIEW_URL / HASHVIEW_API_KEY env vars now override config.json,
  so the CLI can be pointed at a local instance without editing config.
- tests/_hashview_local.py + pytest_configure: when HASHVIEW_TEST_LOCAL=1,
  bring up + seed the Hashview compose stack (HASHVIEW_REPO), verify
  authenticated API access, export the HASHVIEW_* env, and tear down
  (HASHVIEW_KEEP=1 keeps it). Runs in configure so collection-time skipif
  on HASHVIEW_TEST_REAL sees the exported env.
- tests/hashview_local_seed.py: seed an admin api_key + non-default password
  (else Hashview's setup guard redirects every request to /setup), a
  customer, a hashfile, and cracked "effective task" data (else /v1/jobs/add
  has no tasks to schedule).
- api.py: download_left_hashes now uses GET /v1/hashfiles/<id>; the old
  /v1/hashfiles/<id>/left route 404s on current servers.
- subprocess tests: assert on the CLI's actual output ("Job ID:") rather than
  the literal "Job created", and strip ambient HASHVIEW_* creds from the
  no-key-configured check so the env override doesn't defeat it.
- README/CLAUDE: document HASHVIEW_TEST_LOCAL and the env overrides.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Justin Bollinger
2026-06-25 10:17:49 -04:00
co-authored by Claude Opus 4.8
parent dcf377c3d4
commit 048ed7cac1
8 changed files with 488 additions and 9 deletions
+8 -2
View File
@@ -262,9 +262,15 @@ class TestHashviewAPI:
assert content == b"hash1\nhash2\n"
assert result["size"] == len(content)
# Verify auth headers were passed in the left hashes download call
# Verify auth headers were passed in the left hashes download call.
# The uncracked ("left") hashes come from GET /v1/hashfiles/<id>
# (the trailing /found call is a separate lookup).
call_args_list = api.session.get.call_args_list
left_call = [c for c in call_args_list if "left" in str(c)][0]
left_call = [
c
for c in call_args_list
if "/v1/hashfiles/2" in str(c) and "found" not in str(c)
][0]
assert left_call.kwargs.get("headers") is not None
auth_headers = left_call.kwargs.get("headers")
assert "Cookie" in auth_headers or "uuid" in str(auth_headers)