Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions app/src/components/home/HomeBanners.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useT } from '../../lib/i18n/I18nContext';
import { BILLING_DASHBOARD_URL, DISCORD_INVITE_URL } from '../../utils/links';
import { DISCORD_INVITE_URL, PRICING_URL } from '../../utils/links';
import { openUrl } from '../../utils/openUrl';

function formatUsd(amount: number): string {
Expand Down Expand Up @@ -53,7 +53,7 @@ export function UsageLimitBanner({
<button
type="button"
onClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
className={`cursor-pointer border-b border-dashed font-bold ${styles.button}`}>
{ctaLabel}
Expand Down Expand Up @@ -101,7 +101,7 @@ export function PromotionalCreditsBanner({ promoCredits }: { promoCredits: numbe
<button
type="button"
onClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
className="cursor-pointer border-b border-dashed border-amber-700 font-bold text-amber-700 hover:text-amber-800 dark:border-amber-300 dark:text-amber-300 dark:hover:text-amber-200">
{t('home.banners.getSubscription')}
Expand Down Expand Up @@ -143,7 +143,7 @@ export function EarlyBirdyBanner({ onDismiss }: { onDismiss?: () => void }) {
<button
type="button"
onClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
className="cursor-pointer border-b border-amber-700 border-dashed font-bold text-amber-700 hover:text-amber-800 dark:border-amber-300 dark:text-amber-300 dark:hover:text-amber-200">
{t('home.banners.earlyBirdFirstSub')}
Expand Down
6 changes: 3 additions & 3 deletions app/src/components/home/__tests__/HomeBanners.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { BILLING_DASHBOARD_URL, DISCORD_INVITE_URL } from '../../../utils/links';
import { DISCORD_INVITE_URL, PRICING_URL } from '../../../utils/links';
import { openUrl } from '../../../utils/openUrl';
import {
DiscordBanner,
Expand Down Expand Up @@ -45,7 +45,7 @@ describe('HomeBanners', () => {
);
expect(screen.getByText('Out of Usage')).toBeInTheDocument();
fireEvent.click(screen.getByRole('button', { name: 'Get a subscription' }));
expect(openUrl).toHaveBeenCalledWith(BILLING_DASHBOARD_URL);
expect(openUrl).toHaveBeenCalledWith(PRICING_URL);
});

it('opens the billing dashboard through openUrl from the promotional credits banner', () => {
Expand Down Expand Up @@ -77,7 +77,7 @@ describe('HomeBanners', () => {

fireEvent.click(screen.getByRole('button', { name: /first subscription/i }));

expect(openUrl).toHaveBeenCalledWith(BILLING_DASHBOARD_URL);
expect(openUrl).toHaveBeenCalledWith(PRICING_URL);
});

it('does not render a dismiss button when onDismiss is not provided', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';

import { BILLING_DASHBOARD_URL, DISCORD_INVITE_URL } from '../../utils/links';
import { DISCORD_INVITE_URL, PRICING_URL } from '../../utils/links';
import MedullaOverviewPanel from './MedullaOverviewPanel';

// Pass-through translator so assertions can target the i18n keys directly.
Expand Down Expand Up @@ -31,6 +31,6 @@ describe('MedullaOverviewPanel', () => {
it('opens the billing dashboard when the subscription CTA is clicked', () => {
render(<MedullaOverviewPanel />);
fireEvent.click(screen.getByTestId('orch-medulla-subscribe'));
expect(openUrl).toHaveBeenCalledWith(BILLING_DASHBOARD_URL);
expect(openUrl).toHaveBeenCalledWith(PRICING_URL);
});
});
4 changes: 2 additions & 2 deletions app/src/components/orchestration/MedullaOverviewPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* ("Medulla", "OpenHuman", "Discord") stay in every locale.
*/
import { useT } from '../../lib/i18n/I18nContext';
import { BILLING_DASHBOARD_URL, DISCORD_INVITE_URL } from '../../utils/links';
import { DISCORD_INVITE_URL, PRICING_URL } from '../../utils/links';
import { openUrl } from '../../utils/openUrl';

export default function MedullaOverviewPanel() {
Expand Down Expand Up @@ -79,7 +79,7 @@ export default function MedullaOverviewPanel() {
<button
type="button"
data-testid="orch-medulla-subscribe"
onClick={() => void openUrl(BILLING_DASHBOARD_URL)}
onClick={() => void openUrl(PRICING_URL)}
className="mt-auto flex w-full items-center justify-center gap-2 rounded-xl bg-primary-500 px-4 py-2 text-xs font-semibold text-content-inverted shadow-soft transition-colors hover:bg-primary-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1">
{t('orchPage.medulla.subscriberCta')}
</button>
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/settings/panels/BillingPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('<BillingPanel />', () => {

fireEvent.click(screen.getByRole('button', { name: 'Open billing dashboard' }));
await waitFor(() => expect(openUrlMock).toHaveBeenCalledTimes(1));
expect(openUrlMock).toHaveBeenLastCalledWith('https://tinyhumans.ai/pricing');
expect(openUrlMock).toHaveBeenLastCalledWith('https://tinyhumans.ai/dashboard');
});

it('invokes the navigation back handler from both the header and the inline button', async () => {
Expand Down
6 changes: 3 additions & 3 deletions app/src/components/upsell/GlobalUpsellBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useUsageState } from '../../hooks/useUsageState';
import { useT } from '../../lib/i18n/I18nContext';
import { BILLING_DASHBOARD_URL } from '../../utils/links';
import { PRICING_URL } from '../../utils/links';
import { openUrl } from '../../utils/openUrl';
import UpsellBanner from './UpsellBanner';

Expand All @@ -20,7 +20,7 @@ export default function GlobalUpsellBanner() {
ctaLabel={t('chat.upgrade')}
rounded={false}
onCtaClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
/>
</div>
Expand All @@ -38,7 +38,7 @@ export default function GlobalUpsellBanner() {
ctaLabel={t('chat.upgrade')}
rounded={false}
onCtaClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/src/config/__tests__/navConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ describe('AVATAR_MENU_ITEMS', () => {
expect(openUrlItems).toEqual(['billing']);
});

it('opens billing on the public pricing page', () => {
it('opens billing on the authenticated dashboard', () => {
expect(AVATAR_MENU_ITEMS.find(i => i.id === 'billing')?.target).toBe(
'https://tinyhumans.ai/pricing'
'https://tinyhumans.ai/dashboard'
);
});
});
6 changes: 3 additions & 3 deletions app/src/features/conversations/Conversations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ import type { ThreadMessage } from '../../types/thread';
import { splitAgentMessageIntoBubbles } from '../../utils/agentMessageBubbles';
import { chatThreadPath } from '../../utils/chatRoutes';
import { CHAT_ATTACHMENTS_ENABLED } from '../../utils/config';
import { BILLING_DASHBOARD_URL } from '../../utils/links';
import { PRICING_URL } from '../../utils/links';
import { openUrl } from '../../utils/openUrl';
import {
isTauri,
Expand Down Expand Up @@ -2785,7 +2785,7 @@ const Conversations = ({
)}
ctaLabel={t('chat.upgrade')}
onCtaClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
dismissible
onDismiss={() => dismissBanner('conversations-warning')}
Expand Down Expand Up @@ -2830,7 +2830,7 @@ const Conversations = ({
type="button"
data-analytics-id="chat-budget-top-up"
onClick={() => {
void openUrl(BILLING_DASHBOARD_URL);
void openUrl(PRICING_URL);
}}
className="px-3 py-1.5 rounded-lg bg-coral-500 hover:bg-coral-400 text-content-inverted text-xs font-medium transition-colors">
{t('chat.topUp')}
Expand Down
19 changes: 19 additions & 0 deletions app/src/utils/__tests__/desktopDeepLinkListener.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ import { getStoredCoreMode } from '../configPersistence';
import {
authStoreFailureUserMessage,
classifyAuthStoreFailure,
handleDeepLinkUrls,
registerAuthDeepLinkState,
setupDesktopDeepLinkListener,
} from '../desktopDeepLinkListener';
import { BILLING_DASHBOARD_URL } from '../links';
import { openUrl } from '../openUrl';
import { storeSession } from '../tauriCommands';

vi.mock('../configPersistence', () => ({ getStoredCoreMode: vi.fn() }));
vi.mock('../../services/coreRpcClient', () => ({
clearCoreRpcUrlCache: vi.fn(),
clearCoreRpcTokenCache: vi.fn(),
}));
vi.mock('../openUrl', () => ({ openUrl: vi.fn() }));

// Build an `openhuman://auth` deep link bound to a freshly registered state
// nonce, mirroring how the real OAuth button registers the loopback/deep-link
Expand Down Expand Up @@ -83,12 +87,27 @@ describe('desktopDeepLinkListener', () => {
vi.mocked(getStoredCoreMode).mockReturnValue(null);
vi.mocked(clearCoreRpcUrlCache).mockClear();
vi.mocked(clearCoreRpcTokenCache).mockClear();
vi.mocked(openUrl).mockReset();
vi.mocked(openUrl).mockResolvedValue(undefined);
windowControls.show.mockClear();
windowControls.unminimize.mockClear();
windowControls.setFocus.mockClear();
completeDeepLinkAuthProcessing();
});

it('returns successful payment deep links to the billing dashboard', async () => {
await handleDeepLinkUrls(['openhuman://payment/success?session_id=checkout-session']);

expect(openUrl).toHaveBeenCalledWith(BILLING_DASHBOARD_URL);
expect(BILLING_DASHBOARD_URL).toBe('https://tinyhumans.ai/dashboard');
});

it('returns cancelled payment deep links to the billing dashboard', async () => {
await handleDeepLinkUrls(['openhuman://payment/cancel']);

expect(openUrl).toHaveBeenCalledWith(BILLING_DASHBOARD_URL);
});

it('turns Twitter OAuth error deep links into actionable UI and event diagnostics', async () => {
const oauthErrorEvents: CustomEvent[] = [];
window.addEventListener('oauth:error', event => {
Expand Down
3 changes: 2 additions & 1 deletion app/src/utils/links.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const DISCORD_INVITE_URL = 'https://discord.tinyhumans.ai';
export const BILLING_DASHBOARD_URL = 'https://tinyhumans.ai/pricing';
export const PRICING_URL = 'https://tinyhumans.ai/pricing';
export const BILLING_DASHBOARD_URL = 'https://tinyhumans.ai/dashboard';
export const PRIVACY_POLICY_URL = 'https://tinyhumans.gitbook.io/openhuman/legal/privacy-policy';
export const TERMS_OF_USE_URL = 'https://tinyhumans.gitbook.io/openhuman/legal/terms-of-use';
Loading