feat(release): prepare 1.1.0 candidate
This commit is contained in:
parent
5a34f66981
commit
5205dcdfa9
736 changed files with 115667 additions and 12203 deletions
133
apps/mobile-rn/__tests__/ui-native-theme.test.tsx
Normal file
133
apps/mobile-rn/__tests__/ui-native-theme.test.tsx
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
import React from 'react'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import ReactTestRenderer, { act } from 'react-test-renderer'
|
||||
import { AccessibilityInfo, Animated, StyleSheet, View } from 'react-native'
|
||||
import {
|
||||
MetalCard,
|
||||
NativeThemeProvider,
|
||||
PhosphorText,
|
||||
PhysicalButton,
|
||||
WaveBars,
|
||||
d3roNativePalette,
|
||||
} from '@d3ro/ui-native'
|
||||
import { getMobileThemePalette } from '../src/theme/mobile-theme'
|
||||
|
||||
const THEME_PARITY_SCREENS = [
|
||||
'AccountScreen.tsx',
|
||||
'LoginScreen.tsx',
|
||||
'SignUpScreen.tsx',
|
||||
'ForgotPasswordScreen.tsx',
|
||||
'UpdatePasswordScreen.tsx',
|
||||
'HistoryScreen.tsx',
|
||||
'HistoryDetailScreen.tsx',
|
||||
'RecordScreen.tsx',
|
||||
'ProPaywallScreen.tsx',
|
||||
] as const
|
||||
|
||||
function hostByTestId(
|
||||
root: ReactTestRenderer.ReactTestInstance,
|
||||
testID: string,
|
||||
): ReactTestRenderer.ReactTestInstance {
|
||||
const matches = root.findAllByProps({ testID })
|
||||
const host = matches[matches.length - 1]
|
||||
if (host === undefined) throw new Error(`Missing host node: ${testID}`)
|
||||
return host
|
||||
}
|
||||
|
||||
function ThemeFixture({ mode }: { mode: 'light' | 'dark' }): React.ReactElement {
|
||||
const palette = getMobileThemePalette(mode)
|
||||
return (
|
||||
<NativeThemeProvider palette={palette}>
|
||||
<MetalCard testID="theme-card">
|
||||
<PhosphorText testID="theme-text" color="primary">
|
||||
Theme probe
|
||||
</PhosphorText>
|
||||
<PhysicalButton testID="theme-button" label="Continue" />
|
||||
</MetalCard>
|
||||
</NativeThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('ui-native runtime theme boundary', () => {
|
||||
test.each(THEME_PARITY_SCREENS)(
|
||||
'%s resolves colors from mobile preferences at render time',
|
||||
(screenName) => {
|
||||
const source = readFileSync(
|
||||
resolve(__dirname, '..', 'src', 'screens', screenName),
|
||||
'utf8',
|
||||
)
|
||||
expect(source).toContain('useMobilePreferences')
|
||||
expect(source).not.toContain('d3roNativePalette')
|
||||
expect(source).not.toMatch(/const\s+styles\s*=\s*StyleSheet\.create/)
|
||||
},
|
||||
)
|
||||
|
||||
test('updates shared component colors immediately when the provider palette changes', () => {
|
||||
let renderer: ReactTestRenderer.ReactTestRenderer
|
||||
act(() => {
|
||||
renderer = ReactTestRenderer.create(<ThemeFixture mode="dark" />)
|
||||
})
|
||||
|
||||
const dark = getMobileThemePalette('dark')
|
||||
const darkText = hostByTestId(renderer!.root, 'theme-text')
|
||||
const darkCard = hostByTestId(renderer!.root, 'theme-card')
|
||||
const darkButton = hostByTestId(renderer!.root, 'theme-button')
|
||||
expect(StyleSheet.flatten(darkText.props.style).color).toBe(dark.text.primary)
|
||||
expect(StyleSheet.flatten(darkCard.props.style).backgroundColor).toBe(dark.bg.card)
|
||||
expect(StyleSheet.flatten(darkButton.props.style).backgroundColor).toBe(dark.accent.main)
|
||||
|
||||
act(() => {
|
||||
renderer!.update(<ThemeFixture mode="light" />)
|
||||
})
|
||||
|
||||
const light = getMobileThemePalette('light')
|
||||
const lightText = hostByTestId(renderer!.root, 'theme-text')
|
||||
const lightCard = hostByTestId(renderer!.root, 'theme-card')
|
||||
const lightButton = hostByTestId(renderer!.root, 'theme-button')
|
||||
expect(StyleSheet.flatten(lightText.props.style).color).toBe(light.text.primary)
|
||||
expect(StyleSheet.flatten(lightCard.props.style).backgroundColor).toBe(light.bg.card)
|
||||
expect(StyleSheet.flatten(lightButton.props.style).backgroundColor).toBe(light.accent.main)
|
||||
|
||||
act(() => renderer!.unmount())
|
||||
})
|
||||
|
||||
test('keeps the legacy fallback usable outside a provider', () => {
|
||||
let renderer: ReactTestRenderer.ReactTestRenderer
|
||||
act(() => {
|
||||
renderer = ReactTestRenderer.create(
|
||||
<View>
|
||||
<PhosphorText testID="fallback-text">Fallback</PhosphorText>
|
||||
</View>,
|
||||
)
|
||||
})
|
||||
const fallback = hostByTestId(renderer!.root, 'fallback-text')
|
||||
expect(fallback.props.children).toBe('Fallback')
|
||||
expect(StyleSheet.flatten(fallback.props.style).color).toBe(
|
||||
d3roNativePalette.text.primary,
|
||||
)
|
||||
act(() => renderer!.unmount())
|
||||
})
|
||||
|
||||
test('keeps waveform motion stopped when the OS requests reduced motion', async () => {
|
||||
const reduceMotion = jest
|
||||
.spyOn(AccessibilityInfo, 'isReduceMotionEnabled')
|
||||
.mockResolvedValue(true)
|
||||
const loop = jest.spyOn(Animated, 'loop')
|
||||
let renderer: ReactTestRenderer.ReactTestRenderer
|
||||
|
||||
await act(async () => {
|
||||
renderer = ReactTestRenderer.create(
|
||||
<NativeThemeProvider palette={getMobileThemePalette('dark')}>
|
||||
<WaveBars active barCount={2} />
|
||||
</NativeThemeProvider>,
|
||||
)
|
||||
await Promise.resolve()
|
||||
})
|
||||
|
||||
expect(loop).not.toHaveBeenCalled()
|
||||
act(() => renderer!.unmount())
|
||||
loop.mockRestore()
|
||||
reduceMotion.mockRestore()
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue