diff --git a/src/pages/stock/components/PortfolioTab.jsx b/src/pages/stock/components/PortfolioTab.jsx
index 2104fad..9582799 100644
--- a/src/pages/stock/components/PortfolioTab.jsx
+++ b/src/pages/stock/components/PortfolioTab.jsx
@@ -5,26 +5,7 @@ import {
Tooltip as ChartTooltip,
} from 'recharts';
import { formatNumber, formatPercent, toNumeric, profitColorClass, numFitClass } from '../stockUtils';
-
-const formatPriceTime = (iso) => {
- if (!iso) return '';
- const d = new Date(iso);
- if (Number.isNaN(d.getTime())) return '';
- return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
-};
-
-const PriceSessionBadge = ({ session, asOf }) => {
- if (session !== 'NXT_AFTER' && session !== 'NXT_PRE') return null;
- const isPre = session === 'NXT_PRE';
- const label = isPre ? 'NXT 프리' : 'NXT';
- const desc = isPre ? 'NXT 프리마켓 거래가' : 'NXT 야간거래 (15:30~20:00)';
- const time = formatPriceTime(asOf);
- return (
-
- {label}
-
- );
-};
+import PriceSessionBadge from './portfolio/PriceSessionBadge';
const PortfolioTab = ({ pf, asset, handleSell, handleSaveSnapshot }) => (
<>
diff --git a/src/pages/stock/components/portfolio/PriceSessionBadge.jsx b/src/pages/stock/components/portfolio/PriceSessionBadge.jsx
new file mode 100644
index 0000000..390fbd3
--- /dev/null
+++ b/src/pages/stock/components/portfolio/PriceSessionBadge.jsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import { formatPriceTime } from './portfolioUtils';
+
+const PriceSessionBadge = ({ session, asOf }) => {
+ if (session !== 'NXT_AFTER' && session !== 'NXT_PRE') return null;
+ const isPre = session === 'NXT_PRE';
+ const label = isPre ? 'NXT 프리' : 'NXT';
+ const desc = isPre ? 'NXT 프리마켓 거래가' : 'NXT 야간거래 (15:30~20:00)';
+ const time = formatPriceTime(asOf);
+ return (
+
+ {label}
+
+ );
+};
+
+export default PriceSessionBadge;
diff --git a/src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx b/src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx
new file mode 100644
index 0000000..b31ca89
--- /dev/null
+++ b/src/pages/stock/components/portfolio/PriceSessionBadge.test.jsx
@@ -0,0 +1,17 @@
+import { describe, it, expect } from 'vitest';
+import { render, screen } from '@testing-library/react';
+import PriceSessionBadge from './PriceSessionBadge.jsx';
+
+describe('PriceSessionBadge', () => {
+ it('NXT_AFTER → "NXT", NXT_PRE → "NXT 프리"', () => {
+ const { unmount } = render();
+ expect(screen.getByText('NXT')).toBeInTheDocument();
+ unmount();
+ render();
+ expect(screen.getByText('NXT 프리')).toBeInTheDocument();
+ });
+ it('그 외 세션 → 렌더 없음', () => {
+ const { container } = render();
+ expect(container).toBeEmptyDOMElement();
+ });
+});
diff --git a/src/pages/stock/components/portfolio/portfolioUtils.js b/src/pages/stock/components/portfolio/portfolioUtils.js
new file mode 100644
index 0000000..414d01a
--- /dev/null
+++ b/src/pages/stock/components/portfolio/portfolioUtils.js
@@ -0,0 +1,6 @@
+export const formatPriceTime = (iso) => {
+ if (!iso) return '';
+ const d = new Date(iso);
+ if (Number.isNaN(d.getTime())) return '';
+ return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
+};
diff --git a/src/pages/stock/components/portfolio/portfolioUtils.test.js b/src/pages/stock/components/portfolio/portfolioUtils.test.js
new file mode 100644
index 0000000..f9ae276
--- /dev/null
+++ b/src/pages/stock/components/portfolio/portfolioUtils.test.js
@@ -0,0 +1,14 @@
+import { describe, it, expect } from 'vitest';
+import { formatPriceTime } from './portfolioUtils.js';
+
+describe('formatPriceTime', () => {
+ it('유효 ISO → HH:MM (제로패드)', () => {
+ expect(formatPriceTime('2026-07-10T09:05:00')).toBe('09:05');
+ expect(formatPriceTime('2026-07-10T18:30:00')).toBe('18:30');
+ });
+ it('falsy/invalid → 빈 문자열', () => {
+ expect(formatPriceTime('')).toBe('');
+ expect(formatPriceTime(null)).toBe('');
+ expect(formatPriceTime('not-a-date')).toBe('');
+ });
+});