@@ -2453,4 +2453,145 @@ void main() {
2453
2453
..status.equals (AnimationStatus .dismissed);
2454
2454
});
2455
2455
});
2456
+
2457
+ group ('app bar search button' , () {
2458
+ // Tests for the search icon button that should appear in the app bar
2459
+ // on the combined feed screen but not on other message list screens.
2460
+ // We check the app bar's actions list directly to avoid confusion with
2461
+ // the search icon that appears in the search input field.
2462
+
2463
+ testWidgets ('search icon button appears on CombinedFeedNarrow' , (tester) async {
2464
+ // Set up the combined feed (all messages) view
2465
+ await setupMessageListPage (tester, narrow: const CombinedFeedNarrow (), messages: []);
2466
+
2467
+ // Verify that the search button is present in the app bar actions
2468
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2469
+ final actions = appBar.actions ?? [];
2470
+ final hasSearchButton = actions.any ((widget) =>
2471
+ widget is IconButton &&
2472
+ widget.icon is Icon &&
2473
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2474
+ check (hasSearchButton).isTrue ();
2475
+ });
2476
+
2477
+ testWidgets ('search icon button does not appear on ChannelNarrow' , (tester) async {
2478
+ // Set up a single channel view
2479
+ final stream = eg.stream ();
2480
+ await setupMessageListPage (tester, narrow: ChannelNarrow (stream.streamId), messages: []);
2481
+
2482
+ // Verify search button is not present in channel views
2483
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2484
+ final actions = appBar.actions ?? [];
2485
+ final hasSearchButton = actions.any ((widget) =>
2486
+ widget is IconButton &&
2487
+ widget.icon is Icon &&
2488
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2489
+ check (hasSearchButton).isFalse ();
2490
+ });
2491
+
2492
+ testWidgets ('search icon button does not appear on TopicNarrow' , (tester) async {
2493
+ // Set up a single topic view within a channel
2494
+ final stream = eg.stream ();
2495
+ await setupMessageListPage (tester, narrow: eg.topicNarrow (stream.streamId, 'topic' ), messages: []);
2496
+
2497
+ // Verify search button is not present in topic views
2498
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2499
+ final actions = appBar.actions ?? [];
2500
+ final hasSearchButton = actions.any ((widget) =>
2501
+ widget is IconButton &&
2502
+ widget.icon is Icon &&
2503
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2504
+ check (hasSearchButton).isFalse ();
2505
+ });
2506
+
2507
+ testWidgets ('search icon button does not appear on DmNarrow' , (tester) async {
2508
+ // Set up a direct message conversation view
2509
+ final narrow = DmNarrow .withUser (eg.otherUser.userId, selfUserId: eg.selfUser.userId);
2510
+ await setupMessageListPage (tester, narrow: narrow, messages: []);
2511
+
2512
+ // Verify search button is not present in DM views
2513
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2514
+ final actions = appBar.actions ?? [];
2515
+ final hasSearchButton = actions.any ((widget) =>
2516
+ widget is IconButton &&
2517
+ widget.icon is Icon &&
2518
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2519
+ check (hasSearchButton).isFalse ();
2520
+ });
2521
+
2522
+ testWidgets ('search icon button does not appear on MentionsNarrow' , (tester) async {
2523
+ // Set up the mentions view (messages that mention the user)
2524
+ await setupMessageListPage (tester, narrow: const MentionsNarrow (), messages: []);
2525
+
2526
+ // Verify search button is not present in mentions view
2527
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2528
+ final actions = appBar.actions ?? [];
2529
+ final hasSearchButton = actions.any ((widget) =>
2530
+ widget is IconButton &&
2531
+ widget.icon is Icon &&
2532
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2533
+ check (hasSearchButton).isFalse ();
2534
+ });
2535
+
2536
+ testWidgets ('search icon button does not appear on StarredMessagesNarrow' , (tester) async {
2537
+ // Set up the starred messages view
2538
+ await setupMessageListPage (tester, narrow: const StarredMessagesNarrow (), messages: []);
2539
+
2540
+ // Verify search button is not present in starred messages view
2541
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2542
+ final actions = appBar.actions ?? [];
2543
+ final hasSearchButton = actions.any ((widget) =>
2544
+ widget is IconButton &&
2545
+ widget.icon is Icon &&
2546
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2547
+ check (hasSearchButton).isFalse ();
2548
+ });
2549
+
2550
+ testWidgets ('search icon button does not appear on KeywordSearchNarrow' , (tester) async {
2551
+ // Set up the search results view (this is the search page itself)
2552
+ await setupMessageListPage (tester, narrow: KeywordSearchNarrow ('test' ), messages: []);
2553
+
2554
+ // Verify search button is not present on the search page itself
2555
+ // (since the search input field is already present)
2556
+ final appBar = tester.widget <ZulipAppBar >(find.byType (ZulipAppBar ));
2557
+ final actions = appBar.actions ?? [];
2558
+ final hasSearchButton = actions.any ((widget) =>
2559
+ widget is IconButton &&
2560
+ widget.icon is Icon &&
2561
+ (widget.icon as Icon ).icon == ZulipIcons .search);
2562
+ check (hasSearchButton).isFalse ();
2563
+ });
2564
+
2565
+ testWidgets ('search icon button tapping search button on CombinedFeedNarrow navigates to search page' , (tester) async {
2566
+ // Set up navigation tracking
2567
+ final pushedRoutes = < Route <dynamic >> [];
2568
+ final testNavObserver = TestNavigatorObserver ()
2569
+ ..onPushed = (route, prevRoute) => pushedRoutes.add (route);
2570
+
2571
+ // Set up the combined feed view with navigation observer
2572
+ await setupMessageListPage (tester,
2573
+ narrow: const CombinedFeedNarrow (),
2574
+ messages: [],
2575
+ navObservers: [testNavObserver]);
2576
+
2577
+ // Clear any initial navigation that happened during setup
2578
+ pushedRoutes.clear ();
2579
+
2580
+ // Mock the API call for the search page
2581
+ connection.prepare (json: eg.newestGetMessagesResult (
2582
+ foundOldest: true , messages: []).toJson ());
2583
+
2584
+ // Tap the search button in the app bar
2585
+ await tester.tap (find.descendant (
2586
+ of: find.byType (ZulipAppBar ),
2587
+ matching: find.byIcon (ZulipIcons .search)));
2588
+ await tester.pump ();
2589
+
2590
+ // Verify that we navigated to the search page with an empty search query
2591
+ check (pushedRoutes).single.isA <WidgetRoute >().page
2592
+ .isA <MessageListPage >()
2593
+ .initNarrow.equals (KeywordSearchNarrow ('' ));
2594
+ await tester.pump (Duration .zero); // Allow message list fetch to complete
2595
+ });
2596
+ });
2456
2597
}
0 commit comments