Commit Graph
36 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 298e456ff9 [dm] Clear the previous account's DMs on account switch (not just the modal view)
Switching accounts (e.g. NIP-07 → nsec) still showed the OLD account's direct
messages. The earlier switch fix reset only the profile modal's DM view, but the
DM data lives in the app-wide nostrService store (this.dmMessages), which the
messages pane reads via listDirectMessageConversationSummaries /
getDirectMessagesForConversation. Logout clears that store
(stopDirectMessageSubscription + clearDirectMessages); the switch path never did,
so the old messages persisted.

Fix: on an identity change, authSessionCoordinator.handleAuthLogin now stops the
old DM subscription and clears the in-memory DM store BEFORE the new account's
subscription starts — so the pane shows the new account's DMs (or empty→new),
never the old.

Uses a new clearDirectMessages({ keepSnapshot: true }) option: it wipes the
in-memory store but preserves each account's PERSISTED per-actor DM snapshot, so
switching back to an account stays fast (per-account DM cache). Logout still fully
clears (keepSnapshot defaults false).

Tests: tests/services/nostr-service.test.mjs — clearDirectMessages empties the
in-memory store + resets the active actor and emits cleared/updated, in both
keepSnapshot modes. Lint + build green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-01 21:45:23 -04:00
thePR0M3TH3ANandClaude Opus 4.8 6e85c2a32b [storage] fix B2 / generic-S3 uploads ("S3 endpoint is required") — prepareUpload contract
Uploading to a Backblaze B2 (or any generic-S3) bucket failed with "S3 endpoint is
required." even though the connection tested fine.

Root cause: the two upload services have different prepareUpload contracts —
r2Service.prepareUpload(npub, { credentials }) vs s3UploadService.prepareUpload(settings).
MediaUploader calls both the r2 way, so for S3/B2 the npub STRING became the settings →
validateS3Connection saw no endpoint. Compounding it, a storageService.getConnection()
result keeps bucket/endpoint/region under `.meta`, which validateS3Connection reads at
the top level. (R2 worked because its service already uses the (npub, {credentials})
contract.)

Fix:
- s3UploadService.prepareUpload now accepts (npub, { credentials }) AND a direct settings
  object (back-compat), flattening meta → top-level via flattenS3Settings.
- The storage Test now derives/passes the B2 public URL (else the prefix), so it stops
  falsely warning "Public Bucket URL is missing. Uploads will fail."

Tests: tests/services/s3-upload-prepare-contract.test.mjs (3 — meta flatten, npub ignored
when credentials given, direct-settings back-compat). Build + lint clean; upload/storage
suites 46/46.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-30 16:02:37 -04:00
thePR0M3TH3ANandClaude Opus 4.8 0a37e625bb playback: fail over across hosted mirrors before dropping to P2P (#5)
The liveness probe already tries all of a video's sources, but actual playback
only ever tried the single primary URL and then fell straight to WebTorrent. Now
playback fails over across hosted mirrors first.

- PlaybackSession builds an ordered, de-duped hostedSourceCandidates (primary URL
  first, then the video's imeta `sources`; accepts string or {url} entries).
- attemptHostedPlayback takes a candidateUrl; the url-first execution loop tries
  each candidate and advances to the next mirror on probe-fail/stall/timeout,
  cleaning up watchdogs + resetting the <video> between candidates, only calling
  WebTorrent after every hosted mirror fails.
- `sources` plumbed coordinator -> strategy -> session. Single-source videos
  (no `sources`) behave exactly as before.

Tests: tests/services/playbackService_multisource.test.mjs (candidate
construction; the full async fail-over flow is covered by the existing
playbackService_order suite in CI — that mock-timers harness doesn't run in this
sandbox). ROLLBACK: revert the loop to the single attemptHostedPlayback() call
and drop the sources plumbing.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-24 13:30:30 -04:00
thePR0M3TH3ANandClaude Opus 4.8 89747d7290 [playback] CDN-first for dual-source videos + reliable hosted playback
Two fixes for hosted (CDN) playback that users hit on a torrent-first instance:

1. Reliability: clear crossOrigin before direct hosted playback (in
   resetVideoElement and right before video.src = httpsUrl). A leftover
   crossOrigin="anonymous" from a prior WebTorrent attempt on the reused
   <video> forced a CORS request that CDNs / redirect targets (e.g. archive.org
   storage nodes) reject, failing with MEDIA_ERR_SRC_NOT_SUPPORTED ("source not
   supported or blocked"). Direct <video> playback never needs CORS, so any URL
   now plays.

2. CDN-first for dual-source: when a hosted URL exists, play it first for
   instant, reliable startup; WebTorrent is reserved for URL-less videos (and
   explicit forcedSource: "torrent"). Previously a torrent-first instance made
   dual-source videos wait on a P2P cold start before falling back to the CDN.
   The torrent-first branch is now only reached without a URL, so it waits
   indefinitely for peers (no plan B) rather than on a fixed timeout.

Tests: hosted playback clears crossOrigin and plays; a torrent-first instance
plays the URL first when one exists and never calls WebTorrent; URL-less videos
still use WebTorrent. Spec-corrected two playbackService_order tests that
encoded the old torrent-first-for-dual-source behavior. All mutation-verified.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-18 12:15:38 -04:00
thePR0M3TH3ANandClaude Opus 4.8 93b3d6da22 test(s3): integration smoke for the upload -> publish -> cleanup round-trip
Drives the real s3UploadService.uploadVideo for a generic (vhost-style) S3
connection with only the S3 I/O mocked, then feeds the published note's URLs
into r2Service.deleteVideoStorage. Asserts the upload writes video + .thumb +
.torrent, the note is valid (URL + magnet with info-hash), and cleanup deletes
exactly those objects using a forcePathStyle-aware S3 client — i.e. the upload
key and the cleanup-derived key agree (the parity property).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 06:23:06 -04:00
thePR0M3TH3ANandClaude Opus 4.8 fdebf05e1a feat(s3): bring generic S3 to parity with R2 (cleanup + CORS guidance)
Two gaps where generic S3 trailed Cloudflare R2:

1. Object cleanup on delete/edit didn't work for generic S3. deleteVideoStorage
   built its client via makeR2Client, which hard-forces path-style and ignores
   the connection's forcePathStyle -- so vhost-style S3 deletes were misaddressed
   and cleanup silently failed (S3 users' deleted/edited files orphaned). It is
   now provider-aware (mirrors uploadFile): R2 -> makeR2Client (path-style),
   generic S3 -> makeS3Client honoring forcePathStyle. makeS3Client is now
   injectable for testing.

2. CORS guidance on upload failure was R2-only. Extracted isLikelyCorsError +
   a generic-S3 guidance builder into js/utils/uploadErrorHints.js (re-exported
   from r2Service for back-compat); s3UploadService now appends actionable CORS
   guidance on an opaque "Failed to fetch" too.

Generic S3 is now at functional parity with R2 for upload -> publish -> cleanup.

Tests: r2-delete-video-storage (adds generic-S3 forcePathStyle routing),
s3-upload-cors-guidance (new). Full suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 06:13:38 -04:00
thePR0M3TH3ANandClaude Opus 4.8 7f5dcd7e50 fix(upload): attach CORS guidance to direct upload failures
A new user's top first-upload failure is a missing R2 CORS policy (browser
PUT/POST blocked) -- and object-scoped R2 tokens often cannot auto-set CORS.
The connection test already surfaces buildCorsGuidance on the opaque
"Failed to fetch", but a user who skips the test and uploads directly got a
bare "Upload failed: Failed to fetch". The upload error handler now detects the
browser CORS/network rejection (isLikelyCorsError -- Chrome "Failed to fetch",
Firefox "NetworkError", Safari "Load failed") and appends the same actionable
guidance. Updated the R2 follow-up TODO (credential audit done; CORS reviewed).

Test: tests/services/r2-cors-error-classifier.test.mjs. Full suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 05:47:12 -04:00
thePR0M3TH3ANandClaude Opus 4.8 95b51b6e61 feat(r2): delete the underlying storage objects when a video is deleted
Deleting a video removed the Nostr note but left the actual file (plus its
thumbnail and .torrent) publicly downloadable at its R2/S3 URL forever — a
privacy gap and ongoing storage cost. Now the delete flow also removes the
backing objects, best-effort.

- collectVideoStorageKeys() (storagePointer.js): pure helper that derives the
  object keys (video + sibling .torrent + thumbnail) from a note, ONLY for URLs
  under the owner's bucket base — external/3rd-party URLs are never returned.
- R2Service.deleteVideoStorage(): resolves the owner's connection, and deletes
  those keys. Skips cleanly when storage is locked / no creds / no owned
  objects, and never throws (failures are recorded, not propagated) so storage
  cleanup can't block note deletion. R2Service class now exported for testing.
- app.handleDeleteModalConfirm: calls it after handleFullDeleteVideo succeeds.

Tests: tests/storage-key-collection.test.mjs (4),
tests/services/r2-delete-video-storage.test.mjs (4). Full suite green.

Note: superseded versions orphaned by past edits aren't retroactively cleaned;
edit-time cleanup (next) prevents new orphans going forward.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 22:09:57 -04:00
thePR0M3TH3ANandClaude Opus 4.8 3d6ffe997b fix(upload): surface thumbnail/.torrent upload failures to the user
These optional-asset uploads are non-fatal, but failures were warn-only — the
user got a silently-missing thumbnail or torrent with no signal. Both upload
services now emit a 'warning' status at the point of failure and append a note
to the final 'Published' status (downgraded to warning variant) listing what
failed. Cloudflare-upload audit #5.

Test: tests/services/s3-upload-optional-asset-failures.test.mjs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 20:19:27 -04:00
thePR0M3TH3ANandClaude Opus 4.8 6b603cc21c fix(upload): surface an 'Analyzing' status during pre-upload file hashing
Computing the torrent info-hash (and the content-hash fallback) reads the entire
file before the upload starts and before any progress is emitted, so on
multi-GB videos there was a long silent pause that looked like a freeze. Both
upload services now emit an 'Analyzing video…' status when a full-file hash is
required (i.e. no valid info-hash was pre-supplied). Cloudflare-upload audit #2.

Test: tests/services/s3-upload-analyzing-status.test.mjs.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 20:14:21 -04:00
google-labs-jules[bot]andPR0M3TH3AN 99e904d7c1 Optimize explore data worker transfer with lightweight video objects
- Implements `toLightweightVideo` helper in `js/services/exploreDataService.js` to strip large fields (content, signatures, etc.) from video objects before sending to the worker.
- Updates `buildWatchHistoryTagCounts` and `buildTagIdf` to use lightweight objects.
- Adds `tests/services/exploreDataService.optimization.test.mjs` to verify correctness.
- Adds `benchmarks/worker_transfer_lightweight_bench.js` demonstrating ~40% improvement in transfer time.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-11 17:15:25 +00:00
google-labs-jules[bot]andPR0M3TH3AN 3078c46b89 feat(tests): add S3UploadService tests and refactor for testability
- Refactor `S3UploadService` to accept dependencies in constructor
- Move `resolveUploadIdentifier` to class method for mocking
- Add comprehensive unit tests for `S3UploadService` covering event emitter, validation, and upload logic
- Ensure `WebTorrent` dependency is mocked or polyfilled in test environment

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-11 14:42:01 +00:00
google-labs-jules[bot]andPR0M3TH3AN 6fa8df5006 test(services): add unit tests for trustBootstrap.js
Adds a new test file `tests/services/trustBootstrap.test.mjs` to cover the functionality of `bootstrapTrustedSeeds` in `js/services/trustBootstrap.js`.

The test suite covers:
- Feature flag validation
- Successful seed application when access control is ready
- Subscription to access control changes
- Fallback/timeout handling for access control readiness
- Retry logic for relay readiness

Uses `node:test` and mocks dependencies `accessControl`, `moderationService`, `nostrService` via dynamic imports to handle singleton instantiation side effects.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-11 14:15:31 +00:00
google-labs-jules[bot]andPR0M3TH3AN ab72036a4f test(ai): add unit tests for authUtils, decryptionSchemeCache, videoPayloadBuilder (agent)
Added focused unit tests for three core modules to improve coverage:
- `js/services/authUtils.js`: Tested `normalizeProviderId` and `normalizeAuthType`.
- `js/nostr/decryptionSchemeCache.js`: Tested caching logic, TTL expiration, and cache clearing.
- `js/nostr/videoPayloadBuilder.js`: Tested payload extraction and event preparation, including NIP-71 metadata handling.

Tests use `node:test` and `node:assert/strict` and are integrated into the existing test suite.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-11 11:15:09 +00:00
thePR0M3TH3AN 50ab3c7b08 Merge pull request #2209 from PR0M3TH3AN/test/relay-health-improvements-4329305953965740034
test: improve relay health service error handling and robustness
2026-02-07 19:35:37 -05:00
google-labs-jules[bot]andPR0M3TH3AN 596da72cb1 test: improve relay health service error handling and robustness
- Adds a default connection timeout of 5000ms to `RelayHealthService.checkRelay`.
- Adds comprehensive tests for `RelayHealthService` covering:
    - Connection timeouts (mocked).
    - Failure thresholds for user logging.
    - Logging cooldowns (mocked time).
    - Relay `disconnect` and `error` event handling.
    - `nostrClient.markRelayUnreachable` integration.
- Refactors tests to use manual mocking for `setTimeout` and `Date.now` for stability.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-08 00:25:42 +00:00
google-labs-jules[bot]andPR0M3TH3AN 1ac9fee2ed feat(test): Add DiscussionCountService error handling tests
Add comprehensive tests for `DiscussionCountService` focusing on error handling, input validation, and caching.
- Covers happy path, partial results, and unsupported relays.
- Validates graceful degradation when `nostrClient` calls fail.
- Ensures no regression in service functionality.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-08 00:24:54 +00:00
google-labs-jules[bot]andPR0M3TH3AN 24402792a8 test: add unit tests for exploreDataService.js
- Add `tests/services/exploreDataService.test.mjs` to test `buildWatchHistoryTagCounts`.
- Mock global `Worker` to simulate worker behavior.
- Mock `console.warn` to verify error logging and suppression.
- Use dynamic import to handle `devLogger` initialization dependent on global flags.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-07 23:51:11 +00:00
google-labs-jules[bot]andPR0M3TH3AN 6eb86b1459 test(ai): add unit tests for profileMetadataService (agent)
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-07 11:14:03 +00:00
google-labs-jules[bot]andPR0M3TH3AN cfb395ff1a fix(tests): update expected relay health state in unit test
This update aligns `tests/services/relay-health-service.test.mjs` with the actual state object structure used in `RelayHealthService`, which now includes `consecutiveFailures` and `lastUserLogAt` properties. This fixes a CI failure in the `agent-review` job.

The previous fix for `tests/app-batch-fetch-profiles.test.mjs` (duplicate variable) is also included in this branch history.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-30 16:36:27 +00:00
google-labs-jules[bot]andPR0M3TH3AN 959082d327 test(ai): add unit tests for attachmentService, syncMetadataStore, s3Service, dmSignalEvents (agent)
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-28 11:31:13 +00:00
google-labs-jules[bot]andPR0M3TH3AN 415465d067 Fix LinkPreviewService test timeout and assertion failure
Wraps the `respects TTL` test body in a `try...finally` block to ensure `expiredService.db` is closed even if assertions fail, preventing `fake-indexeddb` from hanging during cleanup.
Adds a small delay to the same test to ensure time advances beyond the 0ms TTL (caused by negative TTL clamping), fixing a flaky assertion failure.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 18:36:32 +00:00
google-labs-jules[bot]andPR0M3TH3AN 2ab3f58261 fix(tests): resolve timeout in LinkPreviewService tests by enforcing robust DB closing
- Explicitly nullify `service.db` after closing to prevent reuse or stale references.
- Add `setImmediate` yield in `t.afterEach` to allow `fake-indexeddb` connection close events to propagate before `deleteDatabase`.
- Fixes `[LinkPreviewService Test] Database deletion blocked` causing test timeouts.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 17:49:26 +00:00
google-labs-jules[bot]andPR0M3TH3AN 1f49c5554f test(ai): add unit tests for nip46Queue and moderationActionController (agent)
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 11:54:02 +00:00
google-labs-jules[bot]andPR0M3TH3AN c064ecb548 fix: improve LinkPreviewService test isolation and mock cleanup
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 03:49:59 +00:00
google-labs-jules[bot]andPR0M3TH3AN 65c26b8c1e test: fix LinkPreviewService test isolation
Restores globalThis.fetch after each test in LinkPreviewService test suite to prevent pollution of other tests with mocked implementations.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-01-27 03:30:56 +00:00
google-labs-jules[bot] 4823486ed7 fix(playback): disable timeout and fallback when source is forced by user 2026-01-26 16:12:12 +00:00
google-labs-jules[bot] c22037a575 feat: make default playback source configurable
- Added `DEFAULT_PLAYBACK_SOURCE` to `config/instance-config.js` to allow choosing between "url" (default) and "torrent" priority.
- Updated `js/constants.js` to derive `URL_FIRST_ENABLED` flag from the configuration.
- Refactored `PlaybackService.execute()` in `js/services/playbackService.js` to robustly support "Torrent First" logic with fallback to URL, while maintaining "URL First" with fallback to Torrent.
- Added unit tests in `tests/services/playbackService_order.test.mjs` to verify playback order and fallback mechanics.
2026-01-26 15:13:56 +00:00
google-labs-jules[bot] 603b0b1a69 test(ai): add unit tests for NostrClient and NostrService (agent) 2026-01-26 14:09:53 +00:00
thePR0M3TH3AN 16b8656521 Fix R2 bucket resolution and add coverage 2026-01-26 07:40:23 -05:00
google-labs-jules[bot] df4f7febc2 test(ai): add unit tests for playbackService (agent) 2026-01-23 11:31:37 +00:00
google-labs-jules[bot] f75531d2db chore(ai): format sources and fix moderation bugs (agent)
- Format `css/tailwind.source.css` with Prettier.
- Add allowlist entry for `VideoCard.js` media query pixel value in `scripts/check-design-tokens.mjs`.
- Remove accidental artifact `js/ui/dm/jules_session_4520373547615093905.zip`.
- Fix bug in `js/app.js` and `js/services/moderationActionController.js` where blocked users' videos were not correctly hidden in the UI immediately after blocking.
- Fix bug in `tests/app/moderation-overrides.test.mjs` where `userBlocks` mocks were insufficient to reflect state changes.
2026-01-22 14:58:35 +00:00
google-labs-jules[bot] ebd98dc106 test(ai): add unit tests for storageService (agent) 2026-01-22 11:37:02 +00:00
google-labs-jules[bot] c3770828c0 test(ai): add unit tests for nostr, services, and state (agent) 2026-01-21 11:23:58 +00:00
google-labs-jules[bot] 684f93f6ed test(ai): add unit tests for LinkPreviewService and SessionActor
- Add `tests/services/link-preview-service.test.mjs`: Tests for caching, fetching, and TTL logic using `fake-indexeddb` and `jsdom`.
- Add `tests/nostr/session-actor.test.mjs`: Tests for encryption/decryption and persistence of session actor.
- Refactor `tests/app/similar-content.test.mjs`: Update to test `SimilarContentController` directly, fixing regression caused by architectural changes.
- Ensure tests are self-contained with necessary polyfills (IndexedDB, LocalStorage).
2026-01-20 11:34:30 +00:00
google-labs-jules[bot] 41da0a8361 test(ai): add unit tests for cache, sessionActor, and r2Service (agent)
- Added `tests/state/cache.test.mjs` to test profile persistence and URL health caching.
- Added `tests/nostr/sessionActor.test.mjs` to test session key encryption/decryption and storage.
- Added `tests/services/r2Service.test.mjs` to test R2 settings management and bucket configuration.
- Exposed `__testExports` in `js/nostr/sessionActor.js` to allow testing of private helper functions.
- Used `tests/test-helpers/setup-localstorage.mjs` to mock browser environments in all new tests.
2026-01-19 11:31:46 +00:00