From 1c26d2a3eb638d39dff66b99204ec87ec37452c0 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Fri, 19 Jun 2026 06:32:20 +0300 Subject: [PATCH] fix: improve broker account shell accessibility --- .../src/pages/broker/BrokerAccountLayout.tsx | 4 +- .../src/pages/broker/BrokerPages.test.tsx | 68 ++++++++++++++++++- apps/frontend/src/styles.css | 3 - 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/apps/frontend/src/pages/broker/BrokerAccountLayout.tsx b/apps/frontend/src/pages/broker/BrokerAccountLayout.tsx index f5aaea0..35ac6c9 100644 --- a/apps/frontend/src/pages/broker/BrokerAccountLayout.tsx +++ b/apps/frontend/src/pages/broker/BrokerAccountLayout.tsx @@ -40,9 +40,9 @@ export function BrokerAccountLayout() { -
+
-
+ ); diff --git a/apps/frontend/src/pages/broker/BrokerPages.test.tsx b/apps/frontend/src/pages/broker/BrokerPages.test.tsx index ab13560..919f964 100644 --- a/apps/frontend/src/pages/broker/BrokerPages.test.tsx +++ b/apps/frontend/src/pages/broker/BrokerPages.test.tsx @@ -9,7 +9,7 @@ import * as operationsHook from '../../hooks/useBrokerOperations'; import * as portfolioHook from '../../hooks/useBrokerPortfolio'; import * as positionsHook from '../../hooks/useBrokerPositions'; import type { BrokerPosition } from '../../api/responses'; -import { BrokerAccountLayout } from './BrokerAccountLayout'; +import { BrokerAccountLayout, useBrokerAccountContext } from './BrokerAccountLayout'; import { BrokerAccountDetailPage } from './BrokerAccountDetailPage'; import { BrokerAccountsPage } from './BrokerAccountsPage'; @@ -63,6 +63,19 @@ function mockUseBrokerPositions(...positions: BrokerPosition[]) { }); } +function BrokerAccountContextProbe({ expectedPortfolio }: { expectedPortfolio: unknown }) { + const { accountId, portfolio } = useBrokerAccountContext(); + + return ( +
+

Account context: {accountId}

+

+ {portfolio === expectedPortfolio ? 'Same portfolio query' : 'Different portfolio query'} +

+
+ ); +} + describe('Broker pages', () => { it('renders account section navigation with the current nested route', () => { vi.spyOn(portfolioHook, 'useBrokerPortfolio').mockReturnValue({ @@ -117,6 +130,59 @@ describe('Broker pages', () => { expect(activeLink).toHaveAttribute('aria-current', 'page'); expect(activeLink).toHaveClass('is-active'); expect(screen.getByText('Содержимое облигаций')).toBeInTheDocument(); + expect(screen.queryByRole('main')).not.toBeInTheDocument(); + }); + + it('passes the decoded account and exact portfolio query through outlet context', () => { + const portfolioResult = { + data: { + account: { + id: 'account one', + type: 'brokerage', + name: 'Encoded account', + status: 'ACCOUNT_STATUS_OPEN', + openedAt: null, + accessLevel: null, + }, + totals: { portfolio: { currency: 'RUB', units: '1000', nano: 0, value: 1000 } }, + yields: { expectedPercent: 5, daily: null, dailyPercent: null }, + cash: [], + blockedCash: [], + asOf: '2026-06-17T00:00:00.000Z', + }, + isLoading: false, + isFetching: false, + error: null, + } as any; + const portfolioSpy = vi + .spyOn(portfolioHook, 'useBrokerPortfolio') + .mockReturnValue(portfolioResult); + + renderWithClient( + + }> + } + /> + + , + ['/broker/account%20one/bonds'], + ); + + expect(screen.getByText('Account context: account one')).toBeInTheDocument(); + expect(screen.getByText('Same portfolio query')).toBeInTheDocument(); + expect(portfolioSpy).toHaveBeenCalledWith('account one'); + + const navigation = screen.getByRole('navigation', { name: 'Разделы брокерского счёта' }); + expect(within(navigation).getByRole('link', { name: 'Обзор' })).toHaveAttribute( + 'href', + '/broker/account%20one', + ); + expect(within(navigation).getByRole('link', { name: 'Облигации' })).toHaveAttribute( + 'href', + '/broker/account%20one/bonds', + ); }); it('keeps account navigation and nested content visible when the portfolio is unavailable', () => { diff --git a/apps/frontend/src/styles.css b/apps/frontend/src/styles.css index 4582b85..5e3c383 100644 --- a/apps/frontend/src/styles.css +++ b/apps/frontend/src/styles.css @@ -118,9 +118,6 @@ a { @media (max-width: 720px) { .broker-account__workspace { gap: 16px; - } - - .broker-account__workspace { grid-template-columns: minmax(0, 1fr); }