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

@ -10,6 +10,7 @@ const mockNavigate = jest.fn()
jest.mock('@react-navigation/native', () => {
const ReactValue = require('react') as typeof React
return {
useNavigation: () => ({ goBack: jest.fn() }),
useFocusEffect: (callback: () => void | (() => void)) => {
ReactValue.useEffect(callback, [])
},
@ -18,6 +19,9 @@ jest.mock('@react-navigation/native', () => {
jest.mock('react-native-safe-area-context', () => ({
useSafeAreaInsets: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
}))
jest.mock('../src/navigation/tab-layout', () => ({
useTabScreenBottomPadding: () => 88,
}))
jest.mock('@d3ro/i18n', () => ({
useI18n: () => ({
t: (key: string, params?: Record<string, unknown>) => params === undefined
@ -94,7 +98,7 @@ jest.mock('../src/features/templates', () => ({
loadTemplateLibrary: (...args: unknown[]) => mockLoadTemplateLibrary(...args),
}))
import { TextInput } from 'react-native'
import { FlatList, StyleSheet, TextInput } from 'react-native'
import MeetingsScreen from '../src/screens/MeetingsScreen'
const USER_ID = '11111111-1111-4111-8111-111111111111'
@ -175,6 +179,23 @@ describe('meeting metadata creation screen', () => {
mockCreateMeetingWorkspaceWithMetadata.mockResolvedValue(createdMeeting())
})
test('uses the shared tab and FAB clearance for list content', async () => {
const navigation = {
getParent: () => null,
navigate: mockNavigate,
}
let renderer: ReactTestRenderer
await act(async () => {
renderer = create(<MeetingsScreen navigation={navigation as never} />)
})
await flush()
const list = renderer!.root.findByType(FlatList)
expect(StyleSheet.flatten(list.props.contentContainerStyle).paddingBottom).toBe(88)
expect(list.props.ListFooterComponent).toBeNull()
await act(() => renderer!.unmount())
})
test('submits title, attendees, language, and an explicit template then opens server readback', async () => {
const navigation = {
getParent: () => null,
@ -300,4 +321,37 @@ describe('meeting metadata creation screen', () => {
})
await act(() => renderer!.unmount())
})
test('consumes each FAB create request exactly once', async () => {
const setParams = jest.fn()
const navigation = {
getParent: () => null,
navigate: mockNavigate,
setParams,
}
const route = { params: { createRequest: 1700000000000 } }
let renderer: ReactTestRenderer
await act(async () => {
renderer = create(
<MeetingsScreen navigation={navigation as never} route={route} />,
)
})
await flush()
expect(setParams).toHaveBeenCalledWith({ createRequest: undefined })
expect(mockLoadTemplateLibrary).toHaveBeenCalledTimes(1)
expect(
renderer!.root.findAllByProps({ testID: 'meeting-editor-modal' }).length,
).toBeGreaterThan(0)
await act(async () => {
renderer!.update(
<MeetingsScreen navigation={navigation as never} route={route} />,
)
})
await flush()
expect(mockLoadTemplateLibrary).toHaveBeenCalledTimes(1)
await act(() => renderer!.unmount())
})
})