rn-visual-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React Native Visual Testing for iPhone

React Native iPhone 视觉测试

Test React Native apps visually across iPhone 11–17 families.
针对iPhone 11-17全系列机型进行React Native应用视觉测试。

iPhone Screen Reference

iPhone 屏幕参考

Logical Dimensions (Points) — Use These for Layout Testing

逻辑尺寸(点数)—— 用于布局测试

Device GroupWidthHeightScalePhysicalDiagonal
iPhone 114148962x828×17926.1"
iPhone 11 Pro3758123x1125×24365.85"
iPhone 11 Pro Max4148963x1242×26886.46"
iPhone 12 mini / 13 mini3758123x1080×23405.42"
iPhone 12/12 Pro / 13/13 Pro3908443x1170×25326.06"
iPhone 12/13 Pro Max4289263x1284×27786.68"
iPhone 14 / 14 Pro / 15 / 15 Pro / 16 / 16e3938523x1179×25566.1"
iPhone 14 Plus / 15 Plus4289263x1284×27786.7"
iPhone 14 Pro Max / 15 Pro Max / 16 Plus4309323x1290×27966.7"
iPhone 16 Pro4028743x1206×26226.3"
iPhone 16 Pro Max / 17 Pro Max4409563x1320×28686.9"
iPhone 17 / 17 Pro4028743x1206×26226.3"
iPhone Air4209123x1260×27366.5"
iPhone SE (3rd gen)3756672x750×13344.7"
设备系列宽度高度缩放比例物理分辨率屏幕对角线
iPhone 114148962x828×17926.1"
iPhone 11 Pro3758123x1125×24365.85"
iPhone 11 Pro Max4148963x1242×26886.46"
iPhone 12 mini / 13 mini3758123x1080×23405.42"
iPhone 12/12 Pro / 13/13 Pro3908443x1170×25326.06"
iPhone 12/13 Pro Max4289263x1284×27786.68"
iPhone 14 / 14 Pro / 15 / 15 Pro / 16 / 16e3938523x1179×25566.1"
iPhone 14 Plus / 15 Plus4289263x1284×27786.7"
iPhone 14 Pro Max / 15 Pro Max / 16 Plus4309323x1290×27966.7"
iPhone 16 Pro4028743x1206×26226.3"
iPhone 16 Pro Max / 17 Pro Max4409563x1320×28686.9"
iPhone 17 / 17 Pro4028743x1206×26226.3"
iPhone Air4209123x1260×27366.5"
iPhone SE (3rd gen)3756672x750×13344.7"

Unique Logical Sizes to Test (Minimum Coverage)

需测试的独特逻辑尺寸(最低覆盖范围)

For comprehensive testing, cover these 8 unique logical dimensions:
375×667  — iPhone SE (smallest, no notch, home button)
375×812  — iPhone 11 Pro, 12/13 mini (notch)
390×844  — iPhone 12/13/13 Pro (notch)
393×852  — iPhone 14/14 Pro/15/15 Pro/16/16e (Dynamic Island on Pro)
402×874  — iPhone 16 Pro/17/17 Pro (Dynamic Island)
414×896  — iPhone 11/11 Pro Max (notch, largest of this era)
428×926  — iPhone 12/13 Pro Max, 14 Plus (notch/Dynamic Island)
430×932  — iPhone 14 Pro Max/15 Pro Max/16 Plus (Dynamic Island)
440×956  — iPhone 16 Pro Max/17 Pro Max (largest current)
420×912  — iPhone Air (newest form factor)
为确保测试全面性,需覆盖以下8种独特逻辑尺寸:
375×667  — iPhone SE(最小尺寸,无刘海,带Home键)
375×812  — iPhone 11 Pro、12/13 mini(带刘海)
390×844  — iPhone 12/13/13 Pro(带刘海)
393×852  — iPhone 14/14 Pro/15/15 Pro/16/16e(Pro机型带Dynamic Island)
402×874  — iPhone 16 Pro/17/17 Pro(带Dynamic Island)
414×896  — iPhone 11/11 Pro Max(带刘海,该时期最大尺寸)
428×926  — iPhone 12/13 Pro Max、14 Plus(带刘海/Dynamic Island)
430×932  — iPhone 14 Pro Max/15 Pro Max/16 Plus(带Dynamic Island)
440×956  — iPhone 16 Pro Max/17 Pro Max(当前最大尺寸)
420×912  — iPhone Air(最新形态)

Testing Workflow

测试流程

1. Configure Simulators

1. 配置模拟器

List available simulators:
bash
xcrun simctl list devices available | grep -i iphone
Create missing simulators if needed:
bash
xcrun simctl create "iPhone 15 Pro" "iPhone 15 Pro"
Boot simulator:
bash
xcrun simctl boot "iPhone 15 Pro"
列出可用模拟器:
bash
xcrun simctl list devices available | grep -i iphone
若需创建缺失的模拟器:
bash
xcrun simctl create "iPhone 15 Pro" "iPhone 15 Pro"
启动模拟器:
bash
xcrun simctl boot "iPhone 15 Pro"

2. Run App on Simulator

2. 在模拟器上运行应用

bash
npx react-native run-ios --simulator="iPhone 15 Pro"
Or for specific device:
bash
npx react-native run-ios --device="iPhone 14"
bash
npx react-native run-ios --simulator="iPhone 15 Pro"
或针对特定设备:
bash
npx react-native run-ios --device="iPhone 14"

3. Capture Screenshots

3. 捕获截图

Using simctl:
bash
xcrun simctl io booted screenshot ~/screenshots/iphone15pro_home.png
For all booted simulators:
bash
for UDID in $(xcrun simctl list devices booted -j | jq -r '.devices[][] | select(.state=="Booted") | .udid'); do
  NAME=$(xcrun simctl list devices -j | jq -r ".devices[][] | select(.udid==\"$UDID\") | .name" | tr ' ' '_')
  xcrun simctl io $UDID screenshot ~/screenshots/${NAME}_$(date +%s).png
done
使用simctl:
bash
xcrun simctl io booted screenshot ~/screenshots/iphone15pro_home.png
针对所有已启动的模拟器:
bash
for UDID in $(xcrun simctl list devices booted -j | jq -r '.devices[][] | select(.state=="Booted") | .udid'); do
  NAME=$(xcrun simctl list devices -j | jq -r ".devices[][] | select(.udid==\"$UDID\") | .name" | tr ' ' '_')
  xcrun simctl io $UDID screenshot ~/screenshots/${NAME}_$(date +%s).png
done

4. Set Demo Mode (Consistent Status Bar)

4. 设置演示模式(统一状态栏)

bash
xcrun simctl status_bar booted override \
  --time "9:41" \
  --batteryState charged \
  --batteryLevel 100 \
  --cellularMode active \
  --cellularBars 4 \
  --wifiBars 3
Reset to normal:
bash
xcrun simctl status_bar booted clear
bash
xcrun simctl status_bar booted override \
  --time "9:41" \
  --batteryState charged \
  --batteryLevel 100 \
  --cellularMode active \
  --cellularBars 4 \
  --wifiBars 3
恢复正常模式:
bash
xcrun simctl status_bar booted clear

Visual Testing Tools

视觉测试工具

Detox (Recommended for E2E)

Detox(推荐用于端到端测试)

javascript
// e2e/visual.test.js
describe('Visual Tests', () => {
  beforeAll(async () => {
    await device.launchApp();
    await device.setStatusBar({
      time: '9:41',
      batteryLevel: 100,
      batteryState: 'full',
    });
  });

  it('should match home screen baseline', async () => {
    await device.takeScreenshot('home_screen');
  });
});
javascript
// e2e/visual.test.js
describe('Visual Tests', () => {
  beforeAll(async () => {
    await device.launchApp();
    await device.setStatusBar({
      time: '9:41',
      batteryLevel: 100,
      batteryState: 'full',
    });
  });

  it('should match home screen baseline', async () => {
    await device.takeScreenshot('home_screen');
  });
});

React Native Owl

React Native Owl

javascript
// owl.config.json
{
  "ios": {
    "workspace": "ios/YourApp.xcworkspace",
    "scheme": "YourApp",
    "device": "iPhone 15 Pro"
  },
  "baseline": ".owl/baseline",
  "screenshots": ".owl/screenshots"
}
javascript
// __tests__/Home.owl.js
import { takeScreenshot } from 'react-native-owl';

describe('Home Screen', () => {
  it('matches baseline', async () => {
    const screen = await takeScreenshot('home');
    expect(screen).toMatchBaseline();
  });
});
javascript
// owl.config.json
{
  "ios": {
    "workspace": "ios/YourApp.xcworkspace",
    "scheme": "YourApp",
    "device": "iPhone 15 Pro"
  },
  "baseline": ".owl/baseline",
  "screenshots": ".owl/screenshots"
}
javascript
// __tests__/Home.owl.js
import { takeScreenshot } from 'react-native-owl';

describe('Home Screen', () => {
  it('matches baseline', async () => {
    const screen = await takeScreenshot('home');
    expect(screen).toMatchBaseline();
  });
});

Critical Checkpoints

关键检查点

Safe Area Validation

安全区域验证

Verify content respects safe areas on all devices:
javascript
import { useSafeAreaInsets } from 'react-native-safe-area-context';

// Test that insets are applied correctly:
// - iPhone SE: no top inset (home button device)
// - iPhone 11/12/13: ~47pt top (notch)  
// - iPhone 14 Pro+: ~59pt top (Dynamic Island)
验证所有设备上的内容均遵循安全区域规范:
javascript
import { useSafeAreaInsets } from 'react-native-safe-area-context';

// 测试内边距是否正确应用:
// - iPhone SE:无顶部内边距(带Home键设备)
// - iPhone 11/12/13:顶部约47pt(刘海设备)  
// - iPhone 14 Pro+:顶部约59pt(Dynamic Island设备)

Dynamic Island / Notch Compatibility

Dynamic Island / 刘海兼容性

DeviceTop Element
iPhone SENo notch, 20pt status bar
iPhone 11–13 (non-Pro 14)Notch, ~47pt safe area
iPhone 14 Pro+ / 15 Pro+ / 16+Dynamic Island, ~59pt safe area
设备顶部元素
iPhone SE无刘海,状态栏20pt
iPhone 11–13(非14 Pro系列)刘海,安全区域约47pt
iPhone 14 Pro+ / 15 Pro+ / 16+Dynamic Island,安全区域约59pt

Orientation Testing

横竖屏测试

Test both portrait and landscape:
bash
xcrun simctl io booted screenshot --type=png ~/portrait.png
xcrun simctl spawn booted notifyutil -s com.apple.springboard.orientation 1
sleep 1
xcrun simctl io booted screenshot --type=png ~/landscape.png
测试竖屏与横屏模式:
bash
xcrun simctl io booted screenshot --type=png ~/portrait.png
xcrun simctl spawn booted notifyutil -s com.apple.springboard.orientation 1
sleep 1
xcrun simctl io booted screenshot --type=png ~/landscape.png

Automated Multi-Device Script

多设备自动化脚本

bash
#!/bin/bash
bash
#!/bin/bash

test-all-iphones.sh

test-all-iphones.sh

DEVICES=( "iPhone SE (3rd generation)" "iPhone 11" "iPhone 12 mini" "iPhone 13 Pro" "iPhone 14" "iPhone 14 Pro Max" "iPhone 15" "iPhone 15 Pro Max" "iPhone 16" "iPhone 16 Pro Max" )
SCREENSHOTS_DIR="./visual-tests/$(date +%Y%m%d_%H%M%S)" mkdir -p "$SCREENSHOTS_DIR"
for DEVICE in "${DEVICES[@]}"; do echo "Testing on $DEVICE..."

Boot and wait

xcrun simctl boot "$DEVICE" 2>/dev/null || true sleep 5

Set demo mode

xcrun simctl status_bar "$DEVICE" override --time "9:41" --batteryState charged --batteryLevel 100

Build and run

npx react-native run-ios --simulator="$DEVICE" --no-packager & sleep 30

Capture screenshot

SAFE_NAME=$(echo "$DEVICE" | tr ' ()' '_') xcrun simctl io "$DEVICE" screenshot "$SCREENSHOTS_DIR/${SAFE_NAME}.png"

Shutdown

xcrun simctl shutdown "$DEVICE" done
echo "Screenshots saved to $SCREENSHOTS_DIR"
undefined
DEVICES=( "iPhone SE (3rd generation)" "iPhone 11" "iPhone 12 mini" "iPhone 13 Pro" "iPhone 14" "iPhone 14 Pro Max" "iPhone 15" "iPhone 15 Pro Max" "iPhone 16" "iPhone 16 Pro Max" )
SCREENSHOTS_DIR="./visual-tests/$(date +%Y%m%d_%H%M%S)" mkdir -p "$SCREENSHOTS_DIR"
for DEVICE in "${DEVICES[@]}"; do echo "Testing on $DEVICE..."

启动并等待

xcrun simctl boot "$DEVICE" 2>/dev/null || true sleep 5

设置演示模式

xcrun simctl status_bar "$DEVICE" override --time "9:41" --batteryState charged --batteryLevel 100

构建并运行

npx react-native run-ios --simulator="$DEVICE" --no-packager & sleep 30

捕获截图

SAFE_NAME=$(echo "$DEVICE" | tr ' ()' '_') xcrun simctl io "$DEVICE" screenshot "$SCREENSHOTS_DIR/${SAFE_NAME}.png"

关闭模拟器

xcrun simctl shutdown "$DEVICE" done
echo "Screenshots saved to $SCREENSHOTS_DIR"
undefined

Common Issues

常见问题

IssueSolution
Layout clips on iPhone SEUse flexbox, avoid fixed heights >667pt
Content under Dynamic IslandUse
SafeAreaView
or
useSafeAreaInsets()
Different font renderingCheck
allowFontScaling
prop
Status bar overlapSet
StatusBar
translucent and handle insets
Inconsistent screenshotsEnable demo mode before capture
Bottom home indicator overlapCheck
SafeAreaView
bottom inset
问题解决方案
iPhone SE上布局被截断使用flexbox,避免固定高度超过667pt
内容被Dynamic Island遮挡使用
SafeAreaView
useSafeAreaInsets()
字体渲染不一致检查
allowFontScaling
属性
状态栏重叠设置
StatusBar
为半透明并处理内边距
截图不一致捕获前启用演示模式
底部Home指示器重叠检查
SafeAreaView
底部内边距

Pixel-Perfect Checklist

像素级完美 checklist

  1. ☐ Text readable at all sizes (no truncation)
  2. ☐ Touch targets ≥44pt on all devices
  3. ☐ Images scale correctly (use
    resizeMode
    )
  4. ☐ Safe areas respected (top and bottom)
  5. ☐ Horizontal scrolling only where intended
  6. ☐ No content under notch/Dynamic Island
  7. ☐ Home indicator area clear
  8. ☐ Landscape mode functional (if supported)
  9. ☐ Dark mode appearance correct
  10. ☐ Dynamic Type/font scaling handled
  1. ☐ 所有尺寸下文本均可读(无截断)
  2. ☐ 所有设备上触摸目标≥44pt
  3. ☐ 图片缩放正确(使用
    resizeMode
  4. ☐ 遵循安全区域规范(顶部与底部)
  5. ☐ 仅在预期区域支持横向滚动
  6. ☐ 无内容被刘海/Dynamic Island遮挡
  7. ☐ Home指示器区域无内容遮挡
  8. ☐ 横屏模式可正常工作(若支持)
  9. ☐ 深色模式显示正确
  10. ☐ 适配动态字体/字体缩放