From 782384ba9e585907535cc1440a19e55b8b639b66 Mon Sep 17 00:00:00 2001 From: jtw Date: Mon, 2 Mar 2026 17:37:08 +0900 Subject: [PATCH 1/6] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile/components/ItemModal.test.tsx | 7 +++--- .../profile/components/ProfileHeader.test.tsx | 4 ++-- .../profile/components/ProfileStats.test.tsx | 6 ++--- .../kkuko/profile/utils/profileHelper.test.ts | 22 +++++++++---------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/__tests__/kkuko/profile/components/ItemModal.test.tsx b/src/__tests__/kkuko/profile/components/ItemModal.test.tsx index 5822b54..9692298 100644 --- a/src/__tests__/kkuko/profile/components/ItemModal.test.tsx +++ b/src/__tests__/kkuko/profile/components/ItemModal.test.tsx @@ -13,6 +13,7 @@ jest.mock('@/app/kkuko/profile/utils/profileHelper', () => ({ })); jest.mock('@/app/kkuko/shared/lib/const', () => ({ NICKNAME_COLORS: {}, + OPTION_NAMES: { gEXP: '획득 경험치' } })); describe('ItemModal', () => { @@ -28,7 +29,7 @@ describe('ItemModal', () => { name: 'Cool Hat', image: 'hat.png', desc: 'A nice hat', - options: { score: 10 } + options: { gEXP: 0.1 } }, ] as any; @@ -38,8 +39,8 @@ describe('ItemModal', () => { expect(screen.getByText('장착 아이템 목록')).toBeInTheDocument(); expect(screen.getByText('Cool Hat')).toBeInTheDocument(); - expect(screen.getByText('score:')).toBeInTheDocument(); - expect(screen.getByText('+10')).toBeInTheDocument(); + expect(screen.getByText('gEXP:')).toBeInTheDocument(); + expect(screen.getByText('+10%p')).toBeInTheDocument(); }); it('should call onClose when close button is clicked', () => { diff --git a/src/__tests__/kkuko/profile/components/ProfileHeader.test.tsx b/src/__tests__/kkuko/profile/components/ProfileHeader.test.tsx index 0364cec..2726f26 100644 --- a/src/__tests__/kkuko/profile/components/ProfileHeader.test.tsx +++ b/src/__tests__/kkuko/profile/components/ProfileHeader.test.tsx @@ -37,7 +37,7 @@ describe('ProfileHeader', () => { }); it('should render user info', () => { - render(); + render( {}} isRefreshing={false} />); expect(screen.getByText('Test Nick')).toBeInTheDocument(); expect(screen.getByText('Hello World')).toBeInTheDocument(); @@ -47,7 +47,7 @@ describe('ProfileHeader', () => { }); it('should render badges', () => { - render(); + render( {}} isRefreshing={false} />); expect(screen.getByAltText('Best Badge')).toBeInTheDocument(); }); diff --git a/src/__tests__/kkuko/profile/components/ProfileStats.test.tsx b/src/__tests__/kkuko/profile/components/ProfileStats.test.tsx index 658bed7..122c0ae 100644 --- a/src/__tests__/kkuko/profile/components/ProfileStats.test.tsx +++ b/src/__tests__/kkuko/profile/components/ProfileStats.test.tsx @@ -14,7 +14,7 @@ describe('ProfileStats', () => { beforeEach(() => { (profileHelper.calculateTotalOptions as jest.Mock).mockReturnValue({ - 'str': 10000, + 'hEXP': 10000, 'gEXP': 5000 }); (profileHelper.getOptionName as jest.Mock).mockImplementation((key) => key); @@ -24,8 +24,8 @@ describe('ProfileStats', () => { it('should render total options correctly', () => { render(); - // STR: 10000 -> +10 - expect(screen.getByText('str')).toBeInTheDocument(); + // hEXP: 10000 -> +10 + expect(screen.getByText('hEXP')).toBeInTheDocument(); expect(screen.getByText('+10')).toBeInTheDocument(); // gEXP: 5000 -> +5%p diff --git a/src/__tests__/kkuko/profile/utils/profileHelper.test.ts b/src/__tests__/kkuko/profile/utils/profileHelper.test.ts index 4f0cbfa..7f17ea2 100644 --- a/src/__tests__/kkuko/profile/utils/profileHelper.test.ts +++ b/src/__tests__/kkuko/profile/utils/profileHelper.test.ts @@ -72,13 +72,13 @@ describe('profileHelper', () => { describe('calculateTotalOptions', () => { it('should calculate totals correctly for normal options', () => { const items: ItemInfo[] = [ - { id: '1', name: 'Item1', description: '', group: '', options: { str: 1, dex: 2 }, updatedAt: 1 }, - { id: '2', name: 'Item2', description: '', group: '', options: { str: 3 }, updatedAt: 1 } + { id: '1', name: 'Item1', description: '', group: '', options: { gEXP: 0.01, dex: 2 }, updatedAt: 1 }, + { id: '2', name: 'Item2', description: '', group: '', options: { gEXP: 0.03 }, updatedAt: 1 } ]; const result = calculateTotalOptions(items); - // 1 * 1 + 3 * 1 = 4 - expect(result['str']).toBe(4); - expect(result['dex']).toBe(2); + // 0.01 + 0.03 = 0.04 -> formatted to 4 + expect(result['gEXP']).toBe(4); + expect(result['dex']).toBe(undefined); }); it('should handle special options', () => { @@ -88,14 +88,14 @@ describe('profileHelper', () => { id: '3', name: 'Special', description: '', group: '', options: { date: now - 10000, // Past - before: { str: 1 }, - after: { str: 5 } + before: { gEXP: 0.01 }, + after: { gEXP: 0.05 } }, updatedAt: 1 } ]; const result = calculateTotalOptions(items); // Should use 'after' - expect(result['str']).toBe(5); + expect(result['gEXP']).toBe(5); }); it('should handle special options (before)', () => { @@ -105,14 +105,14 @@ describe('profileHelper', () => { id: '3', name: 'Special', description: '', group: '', options: { date: now + 10000, // Future - before: { str: 1 }, - after: { str: 5 } + before: { gEXP: 0.01 }, + after: { gEXP: 0.05 } }, updatedAt: 1 } ]; const result = calculateTotalOptions(items); // Should use 'before' - expect(result['str']).toBe(1); + expect(result['gEXP']).toBe(1); }); }); From fd7017eb363026c48d2abe0c756539a6136d8a16 Mon Sep 17 00:00:00 2001 From: jtw Date: Mon, 16 Mar 2026 17:58:32 +0900 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/kkuko/shared/components/TryRenderImg.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app/kkuko/shared/components/TryRenderImg.tsx b/src/app/kkuko/shared/components/TryRenderImg.tsx index ad3f5bf..c86d53d 100644 --- a/src/app/kkuko/shared/components/TryRenderImg.tsx +++ b/src/app/kkuko/shared/components/TryRenderImg.tsx @@ -28,10 +28,11 @@ export default function TryRenderImg({ }: Props) { const [attempt, setAttempt] = useState(0); const [failed, setFailed] = useState(false); - const [src, setSrc] = useState(url); - + const isCdn = url.startsWith('https://cdn.kkutu.co.kr/img/'); + const [src, setSrc] = useState(`${isCdn ? 'https://api.solidloop-studio.xyz/kkuko/img?url=' : ''}${url}`); + useEffect(() => { - setSrc(url); + setSrc(`${isCdn ? 'https://api.solidloop-studio.xyz/kkuko/img?url=' : ''}${url}`); setAttempt(0); setFailed(false); }, [url]); @@ -40,8 +41,8 @@ export default function TryRenderImg({ if (attempt < maxRetries) { const next = attempt + 1; setAttempt(next); - const separator = url.includes("?") ? "&" : "?"; - setSrc(`${url}${separator}r=${next}&ts=${Date.now()}`); + const separator = (url.includes("?") || isCdn) ? "&" : "?"; + setSrc(`${isCdn ? 'https://api.solidloop-studio.xyz/kkuko/img?url=' : ''}${url}${separator}r=${next}&ts=${Date.now()}`); } else { setFailed(true); onFailure?.(); @@ -66,6 +67,8 @@ export default function TryRenderImg({ className={className} onError={handleError} onLoad={onLoad} + unoptimized={isCdn} + crossOrigin={isCdn ? "anonymous" : undefined} /> ) : (
@@ -77,6 +80,8 @@ export default function TryRenderImg({ style={{ objectFit: "cover" }} onError={handleError} onLoad={onLoad} + unoptimized={isCdn} + crossOrigin={isCdn ? "anonymous" : undefined} />
)} From 9d213b59e80dd070ca21c1d7bc10991b31151828 Mon Sep 17 00:00:00 2001 From: jtw Date: Mon, 16 Mar 2026 18:00:10 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=98=A8=EB=9D=BC=EC=9D=B8=20=EC=A0=95=EB=B3=B4=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../profile/components/ProfileHeader.tsx | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/app/kkuko/profile/components/ProfileHeader.tsx b/src/app/kkuko/profile/components/ProfileHeader.tsx index 3289f37..a03df03 100644 --- a/src/app/kkuko/profile/components/ProfileHeader.tsx +++ b/src/app/kkuko/profile/components/ProfileHeader.tsx @@ -117,34 +117,6 @@ export default function ProfileHeader({

{formatObservedAt(profileData.user.observedAt)}

-
-

접속 상태

-

- {profileData.presence.channelId ? ( - 온라인 - ) : ( - 오프라인 - )} -

- {profileData.presence.channelId ? ( -

채널: {profileData.presence.channelId}

- ) : ( - profileData.presence.updatedAt !== null ? -

마지막 접속: {formatLastSeen(profileData.presence.updatedAt)}

: - null - )} -
- -
-

방 정보

-

- {profileData.presence.roomId ? ( - 방 {profileData.presence.roomId} - ) : ( - 미입장 - )} -

-