From 501dfd018e31fc22a97077a949c2363da00b55bd Mon Sep 17 00:00:00 2001 From: Tamara Slosarek Date: Tue, 24 Sep 2024 13:54:44 +0200 Subject: [PATCH] test(app): refactor drug page tests --- app/integration_test/drugs_test.dart | 367 ++++++++++-------- ...azole_with_any_not_handled_guideline.dart} | 2 +- ...t => ibuprofen_with_proper_guideline.dart} | 2 +- ...art => mirabegron_without_guidelines.dart} | 2 +- ..._any_not_handled_fallback_guidelines.dart} | 2 +- ...warfarin_with_any_fallback_guideline.dart} | 2 +- app/integration_test/search_test.dart | 12 +- pharme.code-workspace | 2 + 8 files changed, 216 insertions(+), 175 deletions(-) rename app/integration_test/fixtures/drugs/{with_any_not_handled_guideline.dart => aripiprazole_with_any_not_handled_guideline.dart} (96%) rename app/integration_test/fixtures/drugs/{with_proper_guideline.dart => ibuprofen_with_proper_guideline.dart} (97%) rename app/integration_test/fixtures/drugs/{without_guidelines.dart => mirabegron_without_guidelines.dart} (88%) rename app/integration_test/fixtures/drugs/{with_multiple_any_not_handled_fallback_guidelines.dart => pazopanib_with_multiple_any_not_handled_fallback_guidelines.dart} (98%) rename app/integration_test/fixtures/drugs/{with_any_fallback_guideline.dart => warfarin_with_any_fallback_guideline.dart} (96%) diff --git a/app/integration_test/drugs_test.dart b/app/integration_test/drugs_test.dart index 83700bc6..d90b1a61 100644 --- a/app/integration_test/drugs_test.dart +++ b/app/integration_test/drugs_test.dart @@ -7,11 +7,11 @@ import 'package:integration_test/integration_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:provider/provider.dart'; -import 'fixtures/drugs/with_any_fallback_guideline.dart'; -import 'fixtures/drugs/with_any_not_handled_guideline.dart'; -import 'fixtures/drugs/with_multiple_any_not_handled_fallback_guidelines.dart'; -import 'fixtures/drugs/with_proper_guideline.dart'; -import 'fixtures/drugs/without_guidelines.dart'; +import 'fixtures/drugs/aripiprazole_with_any_not_handled_guideline.dart'; +import 'fixtures/drugs/ibuprofen_with_proper_guideline.dart'; +import 'fixtures/drugs/mirabegron_without_guidelines.dart'; +import 'fixtures/drugs/pazopanib_with_multiple_any_not_handled_fallback_guidelines.dart'; +import 'fixtures/drugs/warfarin_with_any_fallback_guideline.dart'; import 'fixtures/set_app_data.dart'; import 'mocks/drug_cubit.dart'; @@ -26,197 +26,236 @@ void main() { UserData.instance.labData = null; UserData.instance.genotypeResults = null; setAppData( - drug: drugWithProperGuideline, - guideline: drugWithProperGuideline.guidelines.first, + drug: ibuprofenWithProperGuideline, + guideline: ibuprofenWithProperGuideline.guidelines.first, ); mockDrugsCubit = MockDrugsCubit(); }); + Future expectDrugContent( + WidgetTester tester, { + required Drug drug, + bool isLoading = false, + bool expectNoGuidelines = false, + bool expectDrugToBeActive = false, + bool expectNoBrandNames = false, + Guideline? guideline, + }) async { + Guideline? relevantGuideline; + if (!expectNoGuidelines) { + relevantGuideline = guideline ?? drug.guidelines.first; + setAppData(drug: drug, guideline: relevantGuideline); + } + when(() => mockDrugsCubit.state) + .thenReturn(isLoading ? DrugState.loading() : DrugState.loaded()); + await tester.pumpWidget( + ChangeNotifierProvider( + create: (context) => ActiveDrugs(), + child: MaterialApp( + home: Scaffold( + body: Builder( + builder: (context) { + return DrugPage(drug, cubit: mockDrugsCubit); + }, + ), + ), + localizationsDelegates: [ + AppLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: [Locale('en', '')], + ), + ), + ); + + // Title + final drugName = isInhibitor(drug.name) ? '${drug.name}*' : drug.name; + expect( + find.text(drugName.capitalize()), + findsOneWidget, + ); + // Activity selection + final activitySelection = tester.firstWidget( + find.byType(Switch) + ) as Switch; + expect(activitySelection.onChanged, isLoading ? isNull : isNotNull); + expect(activitySelection.value, expectDrugToBeActive ? isTrue : isFalse); + // Drug details + expect( + find.textContaining( + drug.annotations.drugclass + ), + findsOneWidget, + ); + expect(find.text(drug.annotations.indication), findsOneWidget); + // Guideline details + final card = tester.firstWidget( + find.byKey( + ValueKey('annotationCard'), + ), + ) as RoundedCard; + expect(find.byType(Disclaimer), findsOneWidget); + final context = tester.element(find.byType(Scaffold).first); + if (expectNoBrandNames) { + expect( + find.textContaining(context.l10n.drug_item_brand_names), + findsNothing, + ); + } else { + expect( + find.textContaining(context.l10n.drug_item_brand_names), + findsOneWidget, + ); + for (final brandName in drug.annotations.brandNames) { + expect( + find.textContaining(brandName), + findsOneWidget, + ); + } + } + if (expectNoGuidelines) { + expect(card.color, WarningLevel.green.color); + expect( + find.byTooltip(context.l10n.drugs_page_tooltip_guideline_missing), + findsOneWidget, + ); + expect( + find.text(context.l10n.drugs_page_guidelines_empty(drug.name)), + findsOneWidget, + ); + expect( + find.text(context.l10n.drugs_page_no_guidelines_text), + findsOneWidget, + ); + } else { + expect(card.color, relevantGuideline!.annotations.warningLevel.color); + expect( + find.byTooltip(context.l10n.drugs_page_tooltip_guideline_present( + relevantGuideline.externalData.first.source, + )), + findsOneWidget, + ); + expect( + find.text(relevantGuideline.annotations.implication), + findsOneWidget, + ); + expect( + find.textContaining(relevantGuideline.annotations.recommendation), + findsOneWidget, + ); + for (final genotypeKey in drug.guidelineGenotypes) { + if (genotypeKey.contains(' ')) { + expect( + find.textContaining(genotypeKey.split(' ').first), + findsOneWidget, + ); + } else { + expect( + find.text(genotypeKey), + findsOneWidget, + ); + } + } + } + } + + Future runTestCasePerGuideline( + Map testCases, { + bool expectNoGuidelines = false, + } + ) async { + for (final (testCase) in testCases.entries) { + final description = 'test drug content with ${testCase.key}'; + final drug = testCase.value; + for (final (index, guideline) in drug.guidelines.indexed) { + // Run per case to ensure clean setup + final caseDescription = drug.guidelines.length > 1 + ? '$description (${index + 1}/${drug.guidelines.length})' + : description; + testWidgets( + caseDescription, + (tester) async { + await expectDrugContent( + tester, + drug: drug, + guideline: guideline, + expectNoGuidelines: expectNoGuidelines, + ); + }, + ); + } + } + } + group('integration test for the drugs page', () { testWidgets( 'test that activity selection is disabled when loading', (tester) async { - await _expectDrugContent( + await expectDrugContent( tester, - mockDrugsCubit, - drug: drugWithProperGuideline, + drug: ibuprofenWithProperGuideline, isLoading: true, ); }, ); testWidgets('test drug content with guideline', (tester) async { - await _expectDrugContent( + await expectDrugContent( tester, - mockDrugsCubit, - drug: drugWithProperGuideline, + drug: ibuprofenWithProperGuideline, ); }); testWidgets('test active drug content', (tester) async { UserData.instance.activeDrugNames = ['ibuprofen']; - await _expectDrugContent( + await expectDrugContent( tester, - mockDrugsCubit, - drug: drugWithProperGuideline, + drug: ibuprofenWithProperGuideline, expectDrugToBeActive: true, ); }); - testWidgets('test drug content without guidelines', (tester) async { - await _expectDrugContent( + testWidgets('test drug without brand names', (tester) async { + final ibuprofenWithoutBrandNames = Drug( + id: ibuprofenWithProperGuideline.id, + version: ibuprofenWithProperGuideline.version, + name: ibuprofenWithProperGuideline.name, + rxNorm: ibuprofenWithProperGuideline.rxNorm, + annotations: DrugAnnotations( + drugclass: ibuprofenWithProperGuideline.annotations.drugclass, + indication: ibuprofenWithProperGuideline.annotations.indication, + brandNames: [], // removed for test + ), + guidelines: ibuprofenWithProperGuideline.guidelines, + ); + await expectDrugContent( tester, - mockDrugsCubit, - drug: drugWithoutGuidelines, - expectNoGuidelines: true, + drug: ibuprofenWithoutBrandNames, + expectNoBrandNames: true, ); }); - }); - group('integration test for special guidelines', () { - testWidgets('test drug content with any fallback guideline', (tester) async { - await _expectDrugContent( - tester, - mockDrugsCubit, - drug: drugWithAnyFallbackGuideline, + group('test missing guidelines', () { + final missingGuidelinesCases = { + 'for drug without guidelines': mirabegronWithoutGuidelines, + }; + runTestCasePerGuideline( + missingGuidelinesCases, + expectNoGuidelines: true, ); }); - final anyNotHandledTestCases = { - 'any not handled fallback guideline': - drugWithAnyNotHandledFallbackGuideline, - 'multiple any not handled fallback guidelines': - drugWithMultipleAnyNotHandledFallbackGuidelines, - }; - for (final (anyNotHandledTestCase) in anyNotHandledTestCases.entries) { - final description = 'test drug content with ${anyNotHandledTestCase.key}'; - final drug = anyNotHandledTestCase.value; - for (final (index, guideline) in drug.guidelines.indexed) { - // Run per case to ensure clean setup - testWidgets( - '$description (${index + 1}/${drug.guidelines.length})', - (tester) async { - await _expectDrugContent( - tester, - mockDrugsCubit, - drug: drug, - guideline: guideline, - ); - }, - ); - } - } + group('test special guidelines', () { + final specialGuidelineTestCases = { + 'any fallback guideline': warfarinWithAnyFallbackGuideline, + 'any not handled fallback guideline': + aripiprazoleWithAnyNotHandledFallbackGuideline, + 'multiple any not handled fallback guidelines': + pazopanibWithMultipleAnyNotHandledFallbackGuidelines, + }; + runTestCasePerGuideline(specialGuidelineTestCases); + }); }); } - -Future _expectDrugContent( - WidgetTester tester, - MockDrugsCubit mockDrugsCubit, { - required Drug drug, - bool isLoading = false, - bool expectNoGuidelines = false, - bool expectDrugToBeActive = false, - Guideline? guideline, -}) async { - Guideline? relevantGuideline; - if (!expectNoGuidelines) { - relevantGuideline = guideline ?? drug.guidelines.first; - setAppData(drug: drug, guideline: relevantGuideline); - } - when(() => mockDrugsCubit.state) - .thenReturn(isLoading ? DrugState.loading() : DrugState.loaded()); - await tester.pumpWidget( - ChangeNotifierProvider( - create: (context) => ActiveDrugs(), - child: MaterialApp( - home: Scaffold( - body: Builder( - builder: (context) { - return DrugPage(drug, cubit: mockDrugsCubit); - }, - ), - ), - localizationsDelegates: [ - AppLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: [Locale('en', '')], - ), - ), - ); - - // Title - final drugName = isInhibitor(drug.name) ? '${drug.name}*' : drug.name; - expect( - find.text(drugName.capitalize()), - findsOneWidget, - ); - // Activity selection - final activitySelection = tester.firstWidget( - find.byType(Switch) - ) as Switch; - expect(activitySelection.onChanged, isLoading ? isNull : isNotNull); - expect(activitySelection.value, expectDrugToBeActive ? isTrue : isFalse); - // Drug details - expect( - find.textContaining( - drug.annotations.drugclass - ), - findsOneWidget, - ); - expect(find.text(drug.annotations.indication), findsOneWidget); - // Guideline details - final card = tester.firstWidget( - find.byKey( - ValueKey('annotationCard'), - ), - ) as RoundedCard; - expect(find.byType(Disclaimer), findsOneWidget); - final context = tester.element(find.byType(Scaffold).first); - if (expectNoGuidelines) { - expect(card.color, WarningLevel.green.color); - expect( - find.byTooltip(context.l10n.drugs_page_tooltip_guideline_missing), - findsOneWidget, - ); - expect( - find.text(context.l10n.drugs_page_guidelines_empty(drug.name)), - findsOneWidget, - ); - expect( - find.text(context.l10n.drugs_page_no_guidelines_text), - findsOneWidget, - ); - } else { - expect(card.color, relevantGuideline!.annotations.warningLevel.color); - expect( - find.byTooltip(context.l10n.drugs_page_tooltip_guideline_present( - relevantGuideline.externalData.first.source, - )), - findsOneWidget, - ); - expect( - find.text(relevantGuideline.annotations.implication), - findsOneWidget, - ); - expect( - find.textContaining(relevantGuideline.annotations.recommendation), - findsOneWidget, - ); - for (final genotypeKey in drug.guidelineGenotypes) { - if (genotypeKey.contains(' ')) { - expect( - find.textContaining(genotypeKey.split(' ').first), - findsOneWidget, - ); - } else { - expect( - find.text(genotypeKey), - findsOneWidget, - ); - } - } - } -} diff --git a/app/integration_test/fixtures/drugs/with_any_not_handled_guideline.dart b/app/integration_test/fixtures/drugs/aripiprazole_with_any_not_handled_guideline.dart similarity index 96% rename from app/integration_test/fixtures/drugs/with_any_not_handled_guideline.dart rename to app/integration_test/fixtures/drugs/aripiprazole_with_any_not_handled_guideline.dart index e3322e71..a2c2a82e 100644 --- a/app/integration_test/fixtures/drugs/with_any_not_handled_guideline.dart +++ b/app/integration_test/fixtures/drugs/aripiprazole_with_any_not_handled_guideline.dart @@ -4,7 +4,7 @@ import 'package:app/common/models/drug/warning_level.dart'; import '../guidelines/aripiprazole_cyp2d6_poor.dart'; -final drugWithAnyNotHandledFallbackGuideline = Drug( +final aripiprazoleWithAnyNotHandledFallbackGuideline = Drug( id: '6492f8e9918ddcae7349c30c', version: 1, name: 'aripiprazole', diff --git a/app/integration_test/fixtures/drugs/with_proper_guideline.dart b/app/integration_test/fixtures/drugs/ibuprofen_with_proper_guideline.dart similarity index 97% rename from app/integration_test/fixtures/drugs/with_proper_guideline.dart rename to app/integration_test/fixtures/drugs/ibuprofen_with_proper_guideline.dart index 4fd27129..074c3795 100644 --- a/app/integration_test/fixtures/drugs/with_proper_guideline.dart +++ b/app/integration_test/fixtures/drugs/ibuprofen_with_proper_guideline.dart @@ -2,7 +2,7 @@ import 'package:app/common/models/drug/drug.dart'; import 'package:app/common/models/drug/guideline.dart'; import 'package:app/common/models/drug/warning_level.dart'; -final drugWithProperGuideline = Drug( +final ibuprofenWithProperGuideline = Drug( id: '6407768b92a4868065b6c466', version: 1, name: 'ibuprofen', diff --git a/app/integration_test/fixtures/drugs/without_guidelines.dart b/app/integration_test/fixtures/drugs/mirabegron_without_guidelines.dart similarity index 88% rename from app/integration_test/fixtures/drugs/without_guidelines.dart rename to app/integration_test/fixtures/drugs/mirabegron_without_guidelines.dart index 307d4d54..30f28711 100644 --- a/app/integration_test/fixtures/drugs/without_guidelines.dart +++ b/app/integration_test/fixtures/drugs/mirabegron_without_guidelines.dart @@ -1,6 +1,6 @@ import 'package:app/common/models/drug/drug.dart'; -final drugWithoutGuidelines = Drug( +final mirabegronWithoutGuidelines = Drug( id: '64c187431006f51bc6e24959', version: 2, name: 'mirabegron', diff --git a/app/integration_test/fixtures/drugs/with_multiple_any_not_handled_fallback_guidelines.dart b/app/integration_test/fixtures/drugs/pazopanib_with_multiple_any_not_handled_fallback_guidelines.dart similarity index 98% rename from app/integration_test/fixtures/drugs/with_multiple_any_not_handled_fallback_guidelines.dart rename to app/integration_test/fixtures/drugs/pazopanib_with_multiple_any_not_handled_fallback_guidelines.dart index cbee7f20..e198fc82 100644 --- a/app/integration_test/fixtures/drugs/with_multiple_any_not_handled_fallback_guidelines.dart +++ b/app/integration_test/fixtures/drugs/pazopanib_with_multiple_any_not_handled_fallback_guidelines.dart @@ -4,7 +4,7 @@ import 'package:app/common/models/drug/warning_level.dart'; import '../guidelines/pazopanib_hlab5701_positive_ugt1a1_poor_guideline.dart'; -final drugWithMultipleAnyNotHandledFallbackGuidelines = Drug( +final pazopanibWithMultipleAnyNotHandledFallbackGuidelines = Drug( id: '6686a865826414ec5b05c44e', version: 1, name: 'pazopanib', diff --git a/app/integration_test/fixtures/drugs/with_any_fallback_guideline.dart b/app/integration_test/fixtures/drugs/warfarin_with_any_fallback_guideline.dart similarity index 96% rename from app/integration_test/fixtures/drugs/with_any_fallback_guideline.dart rename to app/integration_test/fixtures/drugs/warfarin_with_any_fallback_guideline.dart index 90e930f7..9197570d 100644 --- a/app/integration_test/fixtures/drugs/with_any_fallback_guideline.dart +++ b/app/integration_test/fixtures/drugs/warfarin_with_any_fallback_guideline.dart @@ -2,7 +2,7 @@ import 'package:app/common/models/drug/drug.dart'; import 'package:app/common/models/drug/guideline.dart'; import 'package:app/common/models/drug/warning_level.dart'; -final drugWithAnyFallbackGuideline = Drug( +final warfarinWithAnyFallbackGuideline = Drug( id: '658df37b3aa92cbd80bbe352', version: 1, name: 'warfarin', diff --git a/app/integration_test/search_test.dart b/app/integration_test/search_test.dart index 094770c8..3c38fff4 100644 --- a/app/integration_test/search_test.dart +++ b/app/integration_test/search_test.dart @@ -6,9 +6,9 @@ import 'package:integration_test/integration_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:provider/provider.dart'; -import 'fixtures/drugs/with_any_fallback_guideline.dart'; -import 'fixtures/drugs/with_proper_guideline.dart'; -import 'fixtures/drugs/without_guidelines.dart'; +import 'fixtures/drugs/aripiprazole_with_any_not_handled_guideline.dart'; +import 'fixtures/drugs/ibuprofen_with_proper_guideline.dart'; +import 'fixtures/drugs/mirabegron_without_guidelines.dart'; import 'mocks/drug_list_cubit.dart'; void main() { @@ -18,9 +18,9 @@ void main() { binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.onlyPumps; final loadedDrugs = [ - drugWithProperGuideline, - drugWithoutGuidelines, - drugWithAnyFallbackGuideline, + ibuprofenWithProperGuideline, + mirabegronWithoutGuidelines, + aripiprazoleWithAnyNotHandledFallbackGuideline, ]; group('integration test for the search page', () { testWidgets('test search page in loading state', (tester) async { diff --git a/pharme.code-workspace b/pharme.code-workspace index 4b81557b..50f5def8 100644 --- a/pharme.code-workspace +++ b/pharme.code-workspace @@ -38,6 +38,7 @@ "aripiprazole", "atorvastatin", "Backupper", + "brandnames", "bupropion", "cinacalcet", "citalopram", @@ -113,6 +114,7 @@ "unstaged", "userdata", "Vicoprofen", + "VKORC", "voriconazole", "Votrient" ],