feat: add mobile shell and unified search
Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Failing after 50s
ci / 워크스페이스 빌드 검증 (push) Has been skipped
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 20s
ci / .NET API 서버 테스트 (push) Successful in 12s
deploy-site / deploy (push) Successful in 39s
ci / 모바일 린트·타입·Jest (push) Failing after 3h10m31s

This commit is contained in:
Yun Chan 2026-09-28 23:23:36 +09:00
parent f505a03d34
commit 5ca3709b32
98 changed files with 5168 additions and 2093 deletions

View file

@ -1,26 +1,17 @@
import React from 'react'
import ReactTestRenderer, { act } from 'react-test-renderer'
import { I18nProvider } from '@d3ro/i18n'
jest.mock('../src/lib/auth-context', () => ({ useAuth: jest.fn() }))
jest.mock('../src/lib/entitlement-context', () => ({ useEntitlement: jest.fn() }))
jest.mock('../src/lib/native-config', () => ({ getMobileRuntimeConfig: jest.fn() }))
jest.mock('../src/lib/supabase', () => ({ supabase: { from: jest.fn() } }))
jest.mock('../src/lib/preferences-context', () => ({
useMobilePreferences: jest.fn(() => ({
palette: {
accent: { main: '#3366ff' },
bg: { inset: '#111111' },
border: { subtle: '#222222' },
tag: { green: '#00aa66', red: '#cc3344' },
text: {
primary: '#ffffff',
secondary: '#dddddd',
muted: '#999999',
onAccent: '#ffffff',
},
},
})),
}))
jest.mock('../src/lib/preferences-context', () => {
const { d3roNativeDarkPalette } = jest.requireActual('@d3ro/ui-native') as typeof import('@d3ro/ui-native')
return {
useMobilePreferences: jest.fn(() => ({ palette: d3roNativeDarkPalette })),
}
})
const mockedAuth = jest.requireMock('../src/lib/auth-context') as { useAuth: jest.Mock }
const mockedEntitlement = jest.requireMock('../src/lib/entitlement-context') as {
@ -149,7 +140,9 @@ describe('mobile rewarded ad lifecycle', () => {
let renderer: ReactTestRenderer.ReactTestRenderer
await act(async () => {
renderer = ReactTestRenderer.create(
<MobileAdsProvider><FreeTierBanner /></MobileAdsProvider>,
<I18nProvider initialLocale="en">
<MobileAdsProvider><FreeTierBanner /></MobileAdsProvider>
</I18nProvider>,
)
await Promise.resolve()
await Promise.resolve()
@ -157,7 +150,7 @@ describe('mobile rewarded ad lifecycle', () => {
expect(latestBannerProps?.unitId).toBe('ca-app-pub-3940256099942544/6300978111')
act(() => latestBannerProps?.onAdFailedToLoad())
expect(JSON.stringify(renderer!.toJSON())).toContain('AD UNAVAILABLE')
expect(JSON.stringify(renderer!.toJSON())).toContain('Ad unavailable')
await act(async () => {
jest.advanceTimersByTime(30_000)
@ -167,7 +160,7 @@ describe('mobile rewarded ad lifecycle', () => {
expect(latestBannerProps?.unitId).toBe('ca-app-pub-3940256099942544/6300978111')
act(() => latestBannerProps?.onAdLoaded())
expect(JSON.stringify(renderer!.toJSON())).not.toContain('AD UNAVAILABLE')
expect(JSON.stringify(renderer!.toJSON())).not.toContain('Ad unavailable')
act(() => renderer!.unmount())
jest.useRealTimers()
})