Skip to content

fix: copy current session share URL#2324

Closed
AjTheSpidey wants to merge 8 commits into
hyperdxio:mainfrom
AjTheSpidey:codex/share-session-current-url
Closed

fix: copy current session share URL#2324
AjTheSpidey wants to merge 8 commits into
hyperdxio:mainfrom
AjTheSpidey:codex/share-session-current-url

Conversation

@AjTheSpidey
Copy link
Copy Markdown

@AjTheSpidey AjTheSpidey commented May 21, 2026

Fixes #2313.

Found the share button could copy an older URL if the side panel rendered before the session params finished landing in the address bar.

Changed it so the button reads window.location.href when you click it, not during render. I also kept the success/error toast behavior, blocked duplicate clicks while the copy is running, and added tests around the fresh URL + retry cases.

Checked locally:

  • yarn workspace @hyperdx/app jest src/tests/SessionSidePanel.test.tsx --runInBand
  • yarn prettier --check packages/app/src/SessionSidePanel.tsx packages/app/src/tests/SessionSidePanel.test.tsx
  • yarn exec eslint --flag v10_config_lookup_from_file --quiet packages/app/src/SessionSidePanel.tsx packages/app/src/tests/SessionSidePanel.test.tsx
  • yarn workspace @hyperdx/app exec tsc --noEmit --pretty false

@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

@AjTheSpidey is attempting to deploy a commit to the HyperDX Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: 9cad879

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

Deep Review

✅ No critical issues found. The change moves window.location.href capture from render time to click time, adds a synchronous ref guard for duplicate clicks, tracks mount state for post-await toast suppression, and ships a new test file covering URL freshness, error/rejection paths, duplicate-click coalescing, unmount, and StrictMode.

🟡 P2 — recommended

  • packages/app/src/__tests__/SessionSidePanel.test.tsx:194 — no assertion exercises the loading={isSharingSession} prop wired to the Share button, so a regression that hardcodes the prop or skips flipping setIsSharingSession would not be caught even though the duplicate-click ref guard still passes its test.
    • Fix: during the in-flight window of the duplicate-click test, assert screen.getByRole('button', { name: /share session/i }) carries data-loading="true" (or the Mantine spinner is present), and re-assert it clears after finishCopy(true) resolves.
🔵 P3 nitpicks (3)
  • packages/app/src/__tests__/SessionSidePanel.test.tsx:247await new Promise(resolve => setTimeout(resolve, 0)) after finishCopy(true) flushes a single task tick and will silently false-pass if any future await is added between copy resolution and notifications.show.
    • Fix: drain microtasks via repeated await Promise.resolve() ticks, or replace the manual flush with await waitFor(() => expect(notificationsShowSpy).not.toHaveBeenCalled()) after a small bounded delay.
  • packages/app/src/__tests__/SessionSidePanel.test.tsx:137 — URL assertions hard-code http://localhost/sessions?..., coupling the file to jsdom's default origin; a Jest config change to testEnvironmentOptions.url would break every URL assertion even though production behavior is correct.
    • Fix: build expected URLs from ${window.location.origin}/sessions?..., or assert with expect.stringContaining('sid=session-1&sfrom=10&sto=20') for the path-and-query portion only.
  • packages/app/src/__tests__/SessionSidePanel.test.tsx:177 — the rejection-path test verifies the red toast fires but never dispatches a follow-up click, so the catch-branch finally { isSharingSessionRef.current = false } reset is never exercised end-to-end (only the success-branch reset is).
    • Fix: after the rejection-path notification assertion, dispatch a second click and assert copyTextToClipboardMock is called a second time.

Reviewers (9): correctness, testing, maintainability, project-standards, kieran-typescript, julik-frontend-races, reliability, agent-native, learnings-researcher.

Testing gaps: loading-state UI prop transition is not pinned by any assertion; the duplicate-click guard reset on the rejection branch is only indirectly covered.

@AjTheSpidey AjTheSpidey force-pushed the codex/share-session-current-url branch 2 times, most recently from 130d313 to b1fe133 Compare May 22, 2026 18:40
@AjTheSpidey AjTheSpidey force-pushed the codex/share-session-current-url branch 2 times, most recently from 016f943 to a62b13e Compare May 22, 2026 19:27
@AjTheSpidey AjTheSpidey force-pushed the codex/share-session-current-url branch from a62b13e to be021e5 Compare May 22, 2026 19:45
Copy link
Copy Markdown
Contributor

@karl-power karl-power left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! I have a few suggestions to simplify the fix.

Comment on lines +59 to +66
useEffect(() => {
// React 18 StrictMode runs cleanup before re-mounting this effect.
isMountedRef.current = true;

return () => {
isMountedRef.current = false;
};
}, []);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this ref, I'm not sure what it's guarding against? The state update and call to notifications are ok without it

Comment on lines +84 to +87
try {
copied = await copyTextToClipboard(window.location.href);
} catch {
copied = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copyTextToClipboard already wraps both the navigator.clipboard.writeText path and the execCommand fallback in their own try/catch, so I don't think this is needed here.

Comment on lines +76 to +101
const handleShareSession = useCallback(async () => {
if (isSharingSessionRef.current) {
return;
}

isSharingSessionRef.current = true;
setIsSharingSession(true);
let copied = false;
try {
copied = await copyTextToClipboard(window.location.href);
} catch {
copied = false;
} finally {
isSharingSessionRef.current = false;
if (isMountedRef.current) {
setIsSharingSession(false);
}
}
if (!isMountedRef.current) {
return;
}
notifications.show({
color: copied ? 'green' : 'red',
message: copied ? 'Copied link to clipboard' : CLIPBOARD_ERROR_MESSAGE,
});
}, []);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified to:

const handleShareSession = useCallback(async () => {
  if (isSharingSessionRef.current) return;
  isSharingSessionRef.current = true;
  setIsSharingSession(true);

  const copied = await copyTextToClipboard(window.location.href);

  isSharingSessionRef.current = false;
  setIsSharingSession(false);
  notifications.show({
    color: copied ? 'green' : 'red',
    message: copied ? 'Copied link to clipboard' : CLIPBOARD_ERROR_MESSAGE,
  });
}, []);

@pulpdrew
Copy link
Copy Markdown
Contributor

I believe this is fixed with the (slightly) earlier PR #2318

@karl-power karl-power closed this May 28, 2026
@AjTheSpidey AjTheSpidey deleted the codex/share-session-current-url branch May 28, 2026 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Share Session button copies stale URL on first click (missing sid/sfrom/sto)

3 participants