Skip to content

Commit 3453701

Browse files
Komal SinghKomal Singh
authored andcommitted
tests for search icon in app bar inside inbox and combined feed
1 parent 2ef4859 commit 3453701

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed

test/widgets/home_test.dart

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,4 +558,73 @@ void main () {
558558
// TODO end-to-end widget test that checks the error dialog when connecting
559559
// to an ancient server:
560560
// https://github.com/zulip/zulip-flutter/pull/1410#discussion_r1999991512
561+
562+
group('search button', () {
563+
// Tests for the search icon button that should appear in the app bar
564+
// on the inbox tab and allow users to navigate to the search page.
565+
566+
testWidgets('search icon button appears on inbox tab', (tester) async {
567+
await prepare(tester);
568+
// The app starts on the inbox tab by default
569+
// Verify that the search icon button is present in the app bar actions
570+
final appBar = tester.widget<ZulipAppBar>(find.byType(ZulipAppBar));
571+
final actions = appBar.actions ?? [];
572+
final hasSearchButton = actions.any((widget) =>
573+
widget is IconButton &&
574+
widget.icon is Icon &&
575+
(widget.icon as Icon).icon == ZulipIcons.search);
576+
check(hasSearchButton).isTrue();
577+
});
578+
579+
testWidgets('search icon button does not appear on channels tab', (tester) async {
580+
await prepare(tester);
581+
// Switch to the channels (subscribed streams) tab
582+
await tester.tap(find.byIcon(ZulipIcons.hash_italic));
583+
await tester.pump();
584+
// Verify search button is not present on this tab
585+
final appBar = tester.widget<ZulipAppBar>(find.byType(ZulipAppBar));
586+
final actions = appBar.actions ?? [];
587+
final hasSearchButton = actions.any((widget) =>
588+
widget is IconButton &&
589+
widget.icon is Icon &&
590+
(widget.icon as Icon).icon == ZulipIcons.search);
591+
check(hasSearchButton).isFalse();
592+
});
593+
594+
testWidgets('search icon button does not appear on direct messages tab', (tester) async {
595+
await prepare(tester);
596+
// Switch to the direct messages tab
597+
await tester.tap(find.byIcon(ZulipIcons.two_person));
598+
await tester.pump();
599+
// Verify search button is not present on this tab
600+
final appBar = tester.widget<ZulipAppBar>(find.byType(ZulipAppBar));
601+
final actions = appBar.actions ?? [];
602+
final hasSearchButton = actions.any((widget) =>
603+
widget is IconButton &&
604+
widget.icon is Icon &&
605+
(widget.icon as Icon).icon == ZulipIcons.search);
606+
check(hasSearchButton).isFalse();
607+
});
608+
609+
testWidgets('tapping search button navigates to search page', (tester) async {
610+
await prepare(tester);
611+
pushedRoutes.clear();
612+
613+
// Mock the API call that will be made when navigating to search page
614+
connection.prepare(json: eg.newestGetMessagesResult(
615+
foundOldest: true, messages: []).toJson());
616+
617+
// Tap the search button in the app bar
618+
await tester.tap(find.descendant(
619+
of: find.byType(ZulipAppBar),
620+
matching: find.byIcon(ZulipIcons.search)));
621+
await tester.pump();
622+
623+
// Verify that we navigated to the search page (MessageListPage with KeywordSearchNarrow)
624+
check(pushedRoutes).single.isA<WidgetRoute>().page
625+
.isA<MessageListPage>()
626+
.initNarrow.equals(KeywordSearchNarrow(''));
627+
await tester.pump(Duration.zero); // Allow message-list fetch to complete
628+
});
629+
});
561630
}

test/widgets/message_list_test.dart

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,4 +2453,145 @@ void main() {
24532453
..status.equals(AnimationStatus.dismissed);
24542454
});
24552455
});
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+
});
24562597
}

test/widgets/subscription_list_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:flutter_checks/flutter_checks.dart';
44
import 'package:flutter_test/flutter_test.dart';
55
import 'package:zulip/api/model/initial_snapshot.dart';
66
import 'package:zulip/api/model/model.dart';
7+
import 'package:zulip/widgets/app_bar.dart';
78
import 'package:zulip/widgets/color.dart';
89
import 'package:zulip/widgets/home.dart';
910
import 'package:zulip/widgets/icons.dart';
@@ -348,4 +349,21 @@ void main() {
348349
checkStreamNameWght(mutedStreamWithUnmutedUnreads.name, 400);
349350
checkStreamNameWght(mutedStreamWithNoUnmutedUnreads.name, 400);
350351
});
352+
353+
testWidgets('no search button appears in subscribed channels page', (tester) async {
354+
// Set up the subscribed channels (streams) page with one test subscription
355+
await setupStreamListPage(tester, subscriptions: [
356+
eg.subscription(eg.stream(streamId: 1), pinToTop: true),
357+
]);
358+
359+
// Verify that no search button appears in the app bar of the channels page
360+
// (search should only be available on inbox and combined feed)
361+
final appBar = tester.widget<ZulipAppBar>(find.byType(ZulipAppBar));
362+
final actions = appBar.actions ?? [];
363+
final hasSearchButton = actions.any((widget) =>
364+
widget is IconButton &&
365+
widget.icon is Icon &&
366+
(widget.icon as Icon).icon == ZulipIcons.search);
367+
check(hasSearchButton).isFalse();
368+
});
351369
}

0 commit comments

Comments
 (0)