Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor] Remover dependência do Modular ChatMainTalksPage #395

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions lib/app/features/chat/presentation/chat_main_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ChatMainModule extends WidgetModule {
modulesServices: i.get<IAppModulesServices>(),
),
),
Bind.factory<IChatMainTalksController>(
Bind.factory<ChatMainTalksController>(
(i) => ChatMainTalksController(
chatChannelRepository: i.get<IChatChannelRepository>(),
),
Expand All @@ -52,7 +52,13 @@ class ChatMainModule extends WidgetModule {

@override
Widget get view => ChatMainPage(
chatMainPeopleController: Modular.get<ChatMainPeopleController>(),
controller: Modular.get<ChatMainController>(),
chatMainPeopleController: ChatMainPeopleController(
skillRepository: Modular.get<IFilterSkillRepository>(),
usersRepository: Modular.get<IUsersRepository>()),
controller: ChatMainController(
chatToggleFeature: ChatPrivateToggleFeature(
modulesServices: Modular.get<IAppModulesServices>())),
chatMainTalksController: ChatMainTalksController(
chatChannelRepository: Modular.get<IChatChannelRepository>()),
Comment on lines +55 to +62
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Para melhorar a lógica, é melhor manter a criação do controllers no Bind (onde já estão) e aqui consumir a injeção, melhorando a organização e a manutenibilidade do código.

Suggested change
chatMainPeopleController: ChatMainPeopleController(
skillRepository: Modular.get<IFilterSkillRepository>(),
usersRepository: Modular.get<IUsersRepository>()),
controller: ChatMainController(
chatToggleFeature: ChatPrivateToggleFeature(
modulesServices: Modular.get<IAppModulesServices>())),
chatMainTalksController: ChatMainTalksController(
chatChannelRepository: Modular.get<IChatChannelRepository>()),
chatMainPeopleController: Modular.get<ChatMainPeopleController>(),
controller: Modular.get<ChatMainController>(),
chatMainTalksController: Modular.get<ChatMainTalksController>(),

);
}
18 changes: 14 additions & 4 deletions lib/app/features/chat/presentation/chat_main_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ import '../domain/entities/chat_tab_item.dart';
import 'chat_main_controller.dart';
import 'people/chat_main_people_controller.dart';
import 'people/chat_main_people_page.dart';
import 'talk/chat_main_talks_controller.dart';
import 'talk/chat_main_talks_page.dart';

class ChatMainPage extends StatefulWidget {
const ChatMainPage(
{Key? key,
required this.chatMainPeopleController,
required this.controller})
required this.controller,
required this.chatMainTalksController})
: super(key: key);

final ChatMainPeopleController chatMainPeopleController;
final ChatMainController controller;
final ChatMainTalksController chatMainTalksController;

@override
_ChatMainPageState createState() => _ChatMainPageState();
Expand All @@ -26,6 +29,9 @@ class _ChatMainPageState extends State<ChatMainPage> {
ChatMainController get controller => widget.controller;
ChatMainPeopleController get chatMainPeopleController =>
widget.chatMainPeopleController;
ChatMainTalksController get chatMainTalksController =>
widget.chatMainTalksController;

@override
Widget build(BuildContext context) {
return Observer(
Expand All @@ -41,10 +47,12 @@ class _ChatMainPageState extends State<ChatMainPage> {

extension _ChatMainBuilder on _ChatMainPageState {
Widget buildSupportChat() {
return const SafeArea(
return SafeArea(
child: SizedBox.expand(
child: Scaffold(
body: ChatMainTalksPage(),
body: ChatMainTalksPage(
controller: chatMainTalksController,
),
),
),
);
Expand Down Expand Up @@ -88,7 +96,9 @@ extension _ChatMainPageStatePrivate on _ChatMainPageState {
? ChatMainPeoplePage(
controller: chatMainPeopleController,
)
: const ChatMainTalksPage(),
: ChatMainTalksPage(
controller: chatMainTalksController,
),
);
return TabBarView(children: widgets.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@ class ChatMainTalksController = IChatMainTalksController
abstract class IChatMainTalksController with Store, MapFailureMessage {
IChatMainTalksController({
required IChatChannelRepository chatChannelRepository,
}) : _chatChannelRepository = chatChannelRepository {
_init();
}
}) : _chatChannelRepository = chatChannelRepository;

final IChatChannelRepository _chatChannelRepository;

Future<void> _init() async {
Future<void> initialize() async {
await loadScreen();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_modular/flutter_modular.dart';

import '../../../../shared/design_system/colors.dart';
import '../../../authentication/presentation/shared/page_progress_indicator.dart';
Expand All @@ -12,14 +11,24 @@ import '../pages/chat_channel_card.dart';
import 'chat_main_talks_controller.dart';

class ChatMainTalksPage extends StatefulWidget {
const ChatMainTalksPage({Key? key}) : super(key: key);
const ChatMainTalksPage({Key? key, required this.controller})
: super(key: key);

final ChatMainTalksController controller;

@override
_ChatMainTalksPageState createState() => _ChatMainTalksPageState();
}

class _ChatMainTalksPageState
extends ModularState<ChatMainTalksPage, IChatMainTalksController> {
class _ChatMainTalksPageState extends State<ChatMainTalksPage> {
ChatMainTalksController get controller => widget.controller;

@override
void initState() {
super.initState();
controller.initialize();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Melhor garantir que o controller seja acionado apenas quando as Widgets estiverem prontas para isto

Suggested change
controller.initialize();
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.initialize();
});

}

@override
Widget build(BuildContext context) {
return Container(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ class SupportCenterModule extends WidgetModule {

@override
Widget get view => SupportCenterPage(
controller: Modular.get<SupportCenterController>(),
controller: SupportCenterController(
supportCenterUseCase: SupportCenterUseCase(
locationService: Modular.get<ILocationServices>(),
supportCenterRepository: SupportCenterRepository(
apiProvider: Modular.get<ApiProvider>()))),
Comment on lines +53 to +57
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não entendi a necessidade de alterar este código, não entendi a relação desta alteração com o PR

);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:dartz/dartz.dart' show right, left;
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:flutter_modular_test/flutter_modular_test.dart';
import 'package:flutter_test/flutter_test.dart';
Expand All @@ -12,27 +13,23 @@ import 'package:penhas/app/features/chat/domain/entities/chat_channel_entity.dar
import 'package:penhas/app/features/chat/domain/entities/chat_channel_open_entity.dart';
import 'package:penhas/app/features/chat/domain/entities/chat_user_entity.dart';
import 'package:penhas/app/features/chat/domain/repositories/chat_channel_repository.dart';
import 'package:penhas/app/features/chat/presentation/chat_main_module.dart';
import 'package:penhas/app/features/chat/presentation/pages/chat_assistant_card.dart';
import 'package:penhas/app/features/chat/presentation/pages/chat_channel_card.dart';
import 'package:penhas/app/features/chat/presentation/talk/chat_main_talks_controller.dart';
import 'package:penhas/app/features/chat/presentation/talk/chat_main_talks_page.dart';

import '../../../../../utils/golden_tests.dart';
import '../../../../../utils/module_testing.dart';

void main() {
group(ChatMainTalksPage, () {
late IChatChannelRepository mockRepository;
late IModularNavigator mockNavigator;

late ChatMainTalksController controller;
setUp(() {
mockRepository = _MockChatChannelRepository();
Modular.navigatorDelegate = mockNavigator = _MockModularNavigate();

loadModules(
[ChatMainModule()],
overrides: [
Bind<IChatChannelRepository>((i) => mockRepository),
],
);
controller =
ChatMainTalksController(chatChannelRepository: mockRepository);

when(() => mockRepository.listChannel()).thenAnswer(
(_) async => right(_chatChannelAvailableFixture),
Expand All @@ -42,13 +39,17 @@ void main() {
screenshotTest(
'loaded state should be rendered',
fileName: 'chat_main_talks_page_initial_state',
pageBuilder: () => ChatMainTalksPage(),
pageBuilder: () => ChatMainTalksPage(
controller: controller,
),
);

screenshotTest(
'error state should be rendered',
fileName: 'chat_main_talks_page_error_state',
pageBuilder: () => ChatMainTalksPage(),
pageBuilder: () => ChatMainTalksPage(
controller: controller,
),
setUp: () {
when(() => mockRepository.listChannel()).thenAnswer(
(_) async => left(ServerFailure()),
Expand All @@ -60,7 +61,9 @@ void main() {
'should navigate to assistant quiz when open assistant card',
(tester) => mockNetworkImages(() async {
// arrange
final widget = buildTestableWidget(ChatMainTalksPage());
final widget = buildTestableWidget(ChatMainTalksPage(
controller: controller,
));
await tester.pumpWidget(widget);
await tester.pumpAndSettle();
when(
Expand Down Expand Up @@ -89,7 +92,9 @@ void main() {
'should navigate to support chat when open support card',
(tester) => mockNetworkImages(() async {
// arrange
final widget = buildTestableWidget(ChatMainTalksPage());
final widget = buildTestableWidget(ChatMainTalksPage(
controller: controller,
));
await tester.pumpWidget(widget);
await tester.pumpAndSettle();
when(
Expand Down Expand Up @@ -117,7 +122,9 @@ void main() {
'should navigate to chat page when open conversation card',
(tester) => mockNetworkImages(() async {
// arrange
final widget = buildTestableWidget(ChatMainTalksPage());
final widget = buildTestableWidget(ChatMainTalksPage(
controller: controller,
));
await tester.pumpWidget(widget);
await tester.pumpAndSettle();
when(
Expand All @@ -139,6 +146,86 @@ void main() {
).called(1);
}),
);

testWidgets(
'should display loading state',
(tester) => mockNetworkImages(() async {
// arrange
when(() => mockRepository.listChannel()).thenAnswer(
(_) async => right(_chatChannelAvailableFixture),
);
// act
await tester.pumpWidget(
MaterialApp(
home: ChatMainTalksPage(controller: controller),
),
);
await tester.pumpAndSettle();

// Assert
expect(find.byType(ChatChannelCard), findsNWidgets(2));
expect(find.byType(ChatAssistantCard), findsNWidgets(2));
expect(find.text('Suas conversas (2)'), findsOneWidget);
}),
);

testWidgets(
'should trigger refresh and fetch new data when pull to refresh is activated',
(tester) => mockNetworkImages(() async {
// arrange
when(() => mockRepository.listChannel()).thenAnswer(
(_) async => right(_chatChannelAvailableFixture),
);
// act
await tester.pumpWidget(
MaterialApp(
home: ChatMainTalksPage(controller: controller),
),
);
await tester.pumpAndSettle();

// Primeira chamada durante initialize
verify(() => mockRepository.listChannel()).called(1);

await tester.drag(find.byType(ListView), const Offset(0, 300));
await tester.pumpAndSettle();

// Assert
// Segunda chamada durante o refresh
verify(() => mockRepository.listChannel()).called(1);
}),
);

testWidgets(
'should navigate to chat when assistant card is tapped',
(tester) => mockNetworkImages(() async {
// arrange
when(() => mockRepository.listChannel()).thenAnswer(
(_) async => right(_chatChannelAvailableFixture),
);

when(() => mockNavigator.popAndPushNamed(any(),
arguments: any(named: 'arguments')))
.thenAnswer((_) => Future.value());

await tester.pumpWidget(
MaterialApp(
home: ChatMainTalksPage(controller: controller),
),
);
await tester.pumpAndSettle();
// act
await tester.tap(find.text('Assistente PenhaS'));
await tester.pumpAndSettle();
// assert
verify(
() => mockNavigator.popAndPushNamed(
'/quiz?origin=chat',
arguments: any(named: 'arguments'),
),
).called(1);
}),
);
});
}

Expand Down
Loading