導航路徑 test
導航路徑 test 驗證的是使用者在畫面之間的移動是否符合設計 — 每個畫面的 back 按鈕是否導向正確的上層畫面、每個 router 定義的路由是否從 UI 可達、go 和 push 的語意是否產生正確的返回堆疊。
Back 按鈕 test
每個有 back 按鈕的畫面需要一個 test 驗證「按下 back 後導航到哪裡」。Back 按鈕的目標畫面依導航方式而定:
context.push('/terminal')進入 → back 回到推入前的畫面(首頁)context.go('/terminal')進入 → back 行為依 router 設定,可能沒有上一頁
1testWidgets('back from terminal returns to home (pushed)', (tester) async {
2 await tester.pumpWidget(app());
3 // 從首頁 push 到 terminal
4 await tester.tap(find.text('Connect Terminal'));
5 await tester.pumpAndSettle();
6 expect(find.byType(TerminalScreen), findsOneWidget);
7 // 按 back
8 await tester.tap(find.byKey(Key('back_button')));
9 await tester.pumpAndSettle();
10 expect(find.byType(HomeScreen), findsOneWidget);
11});Route 可達性 test
Router 定義的每個路由都應該有從 UI 可達的路徑(ux-design 模組一 路由可達性)。Route 可達性 test 驗證「從首頁出發,透過 UI 操作能到達每個路由」。
1testWidgets('enrollment route is reachable from home', (tester) async {
2 await tester.pumpWidget(app());
3 // 找到配對入口按鈕
4 final enrollButton = find.text('Enroll Device');
5 expect(enrollButton, findsOneWidget);
6 // 點擊後到達 enrollment 畫面
7 await tester.tap(enrollButton);
8 await tester.pumpAndSettle();
9 expect(find.byType(EnrollmentScreen), findsOneWidget);
10});不可達的路由在 test 中表現為「找不到導航到該路由的 UI 元素」。如果 router 定義了 /enrollment 但首頁沒有對應按鈕,find.text('Enroll Device') 會找不到元素 — test 失敗暴露入口缺失。
go vs push 語意的 test
go 和 push 對返回堆疊的影響不同(ux-design 模組五 導航模式)。Test 需要驗證正確的導航方式被使用:
Push 語意:保留返回堆疊
Push 後按系統 back 鍵應該回到推入前的畫面。
1testWidgets('push preserves back stack', (tester) async {
2 await tester.pumpWidget(app());
3 // push to enrollment
4 await tester.tap(find.text('Enroll Device'));
5 await tester.pumpAndSettle();
6 // 系統 back 鍵
7 final backButton = find.byTooltip('Back');
8 await tester.tap(backButton);
9 await tester.pumpAndSettle();
10 // 應該回到首頁
11 expect(find.byType(HomeScreen), findsOneWidget);
12});Go 語意:替換路由堆疊
Go 後按系統 back 鍵的行為依 router 設定。如果 go 到的路由是根層級,系統 back 鍵可能退出 app 而非回到前一個畫面。
Test 策略:驗證 go 後的路由堆疊狀態。如果設計意圖是「切換工作區,不保留前一個畫面」,斷言系統 back 鍵不回到前一個畫面。
深層連結 test
深層連結(deep link)讓使用者從 app 外部直接進入特定畫面。Deep link test 驗證「直接導航到內部路由時,畫面和導航堆疊是否正確」。
1testWidgets('deep link to /terminal shows terminal', (tester) async {
2 await tester.pumpWidget(app(initialRoute: '/terminal'));
3 expect(find.byType(TerminalScreen), findsOneWidget);
4});深層連結的特殊性在於使用者跳過了正常的導航流程。從首頁到 terminal 的正常流程可能經過認證 gate,但深層連結直接到 terminal — 認證 gate 是否仍然生效需要額外的 test。
下一步路由
- 狀態覆蓋策略 → Widget test 的狀態覆蓋策略
- Playwright 驗證流程 → Playwright 瀏覽器驗證流程
- 路由可達性的設計原則 → ux-design 模組一 路由可達性