Skip to content

Commit ff3d48b

Browse files
damian-molinskiemirideServercic
authored
fix(cat-voices): flutter integration tests (#3257)
* test(cat-voices): fix integration tests - part 1 (#3061) * test(cat-voices): fix integration tests * building flutter driver and simplest test * fix previous commit * update docs * export test utils * prepare for test accounts * test account * optional unlocked flag * app test * remove warnings * allow awaiting video and asset cache initialisation * allow calling bootstrap in SetUp method * allow awaiting ImagePrecacheService * app tests * account cubit safe checks emits * account tests * chore: remove debug prints * rollback timeline change * simplify tests and fix analyzer * update UserService tests names * RegistrationService createAccount masterKey.use * improve ImagePrecacheService and VideoManager isInitialized completer logic * chore: missing TODO comment * chore: TODO about test accounts * feat: awaiting db operations completion * cleanup * rollback timeline change * remove SemanticsBinding * chore: formatting --------- Co-authored-by: Servercic <[email protected]> Co-authored-by: Damian Moliński <[email protected]> Co-authored-by: Damian Molinski <[email protected]> * chore: code formatting (#3230) * fix(cat-voices): flutter integration tests - part3 (#3240) * fund name text * chore: bring back discovery tests * Change DateTime with DateTimeExt * feat: allow mocking CurrentCampaign and mocking DateTime so specific phase * allow updating dummy * chore: proposals tests * onboarding tests * recovery flow tests * chore: more discovery tests * fix: import * chore: remove splash TODO comment * chore: skip e2e integration tests * fix: analysis --------- Co-authored-by: Emir Hodzic <[email protected]> Co-authored-by: Servercic <[email protected]>
1 parent f8ef6ac commit ff3d48b

File tree

83 files changed

+1564
-1456
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1564
-1456
lines changed

catalyst_voices/apps/voices/integration_test/Earthfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ integration-test-web:
2828
sleep 5 && \
2929
flutter drive --driver=test_driver/integration_tests.dart \
3030
--target=integration_test/all_test.dart \
31+
--dart-define=ENV_NAME=dev \
3132
-d $browser --driver-port=$driver_port \
3233
--web-header Cross-Origin-Opener-Policy=same-origin \
3334
--web-header Cross-Origin-Embedder-Policy=require-corp \

catalyst_voices/apps/voices/integration_test/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,16 @@ To run the integration tests via the command line, use the following command:
7474

7575
```bash
7676
flutter drive \
77+
--dart-define=ENV_NAME=dev \
7778
--web-header Cross-Origin-Opener-Policy=same-origin \
7879
--web-header Cross-Origin-Embedder-Policy=require-corp \
7980
--driver=test_driver/integration_tests.dart \
8081
--target=integration_test/all_test.dart \
8182
-d chrome
8283
```
8384

85+
Where `ENV_NAME` can be `dev`|`preprod`|`prod`|`relative`.
86+
8487
### Via Visual Studio Code
8588

8689
To run the tests in Visual Studio Code,
Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,63 @@
11
import 'package:catalyst_voices/configs/bootstrap.dart';
2+
import 'package:catalyst_voices/dependency/dependencies.dart';
3+
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
4+
import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
5+
import 'package:catalyst_voices_services/catalyst_voices_services.dart';
6+
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
27
import 'package:flutter_test/flutter_test.dart';
38
import 'package:integration_test/integration_test.dart';
49

5-
import 'suites/account_test.dart' as account_test;
6-
import 'suites/app_test.dart' as app_test;
7-
import 'suites/discovery_test.dart' as discovery_test;
8-
import 'suites/onboarding_restore_test.dart' as onboarding_restore_test;
9-
import 'suites/onboarding_test.dart' as onboarding_test;
10-
import 'suites/proposals_test.dart' as proposals_test;
10+
import 'suites/suites.dart';
1111

12-
void main() async {
12+
void main() {
1313
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
14-
binding.testTextInput.register();
1514

1615
setUpAll(() async {
17-
await bootstrap(router: buildAppRouter());
16+
binding.testTextInput.register();
17+
18+
// F14
19+
final f14Campaign = Campaign.f14();
20+
mockedActiveCampaign = f14Campaign;
21+
22+
final proposalSubmissionTimeline = f14Campaign.timeline.phases
23+
.firstWhere((element) => element.type == CampaignPhaseType.proposalSubmission)
24+
.timeline;
25+
26+
final middle = proposalSubmissionTimeline.middle();
27+
28+
DateTimeExt.mockedDateTime = middle;
29+
});
30+
31+
setUp(() async {
32+
await bootstrap();
33+
34+
await loggingService.updateSettings(printToConsole: const Optional(false));
35+
36+
await Dependencies.instance.get<SyncManager>().waitForSync;
1837
});
19-
app_test.main();
20-
onboarding_restore_test.main();
21-
onboarding_test.main();
22-
account_test.main();
23-
discovery_test.main();
24-
proposals_test.main();
38+
39+
tearDown(() async {
40+
await Dependencies.instance.get<CatalystDatabase>().pendingOperations;
41+
// TODO(damian-molinski): sometimes tests are flaky because of pending db queries
42+
// do not have time to finish. pendingOperations is not implemented correctly
43+
await Future<void>.delayed(const Duration(milliseconds: 500));
44+
45+
await cleanUpStorages();
46+
await cleanUpUserDataFromDatabase();
47+
await Dependencies.instance.reset;
48+
});
49+
50+
tearDownAll(() {
51+
binding.testTextInput.unregister();
52+
});
53+
54+
group('App -', appTests, skip: _skipE2EReason);
55+
group('Account -', accountTests, skip: _skipE2EReason);
56+
group('Discovery space -', discoverySpaceTests, skip: _skipE2EReason);
57+
group('Onboarding -', onboardingTests, skip: _skipE2EReason);
58+
// TODO(emiride): rethink how to setup tests accounts in different environments for gateway.
59+
group('Onboarding Restore Flow -', onboardingRestoreTests, skip: _skipE2EReason);
60+
group('Proposals space -', proposalsTests, skip: _skipE2EReason);
2561
}
62+
63+
const _skipE2EReason = 'No maintained. Playwright implementation in progress';

catalyst_voices/apps/voices/integration_test/pageobject/account_dropdown_page.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:patrol_finders/patrol_finders.dart';
55
import '../utils/translations_utils.dart';
66

77
class AccountDropdownPage {
8-
PatrolTester $;
8+
final PatrolTester $;
99
final profileAndKeychainText = const Key('ProfileAndKeychain');
1010

1111
final popUpMenuAccountHeader = const Key('PopUpMenuAccountHeader');
@@ -18,6 +18,7 @@ class AccountDropdownPage {
1818
final redirectToDocsMenuItem = const Key('CatalystKnowledgeBase');
1919
final segmentedButtonContainer = const Key('segmentedButtonContainer');
2020
final lockAccountButton = const Key('LockAccountButton');
21+
2122
AccountDropdownPage(this.$);
2223

2324
Future<void> accountDropdownContainsSpecificData() async {
@@ -45,7 +46,6 @@ class AccountDropdownPage {
4546
Future<void> accountDropdownLooksAsExpected() async {
4647
expect($(profileAndKeychainText), findsOneWidget);
4748
expect($(segmentedButton), findsWidgets);
48-
expect($(setupRolesMenuItem), findsOneWidget);
4949
expect($(lockAccountButton), findsOneWidget);
5050
}
5151

catalyst_voices/apps/voices/integration_test/pageobject/app_bar_page.dart

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,32 @@ import '../utils/constants.dart';
66
import '../utils/translations_utils.dart';
77

88
class AppBarPage {
9-
late PatrolTester $;
9+
final PatrolTester $;
10+
1011
final spacesDrawerButton = const Key('DrawerButton');
1112
final getStartedBtn = const Key('GetStartedButton');
1213
final finishRegistrationBtn = const Key('FinishRegistrationButton');
1314
final accountPopupBtn = const Key('AccountPopupButton');
1415
final lockBtn = const Key('LockButton');
1516
final unlockBtn = const Key('UnlockButton');
17+
final visitorBtn = const Key('VisitorBtn');
1618
final sessionAccountPopupMenuAvatar = const Key('SessionAccountPopupMenuAvatar');
19+
final createProposalBtn = const Key('CreateProposalButton');
20+
1721
AppBarPage(this.$);
1822

1923
Future<void> accountPopupBtnClick() async {
2024
await $(sessionAccountPopupMenuAvatar).tap();
2125
}
2226

27+
Future<void> createProposalBtnIsNotVisible() async {
28+
expect($(createProposalBtn), findsNothing);
29+
}
30+
31+
Future<void> createProposalBtnIsVisible() async {
32+
expect($(createProposalBtn), findsOneWidget);
33+
}
34+
2335
Future<void> finishAccountCreationBtnIsVisible() async {
2436
expect($(finishRegistrationBtn), findsOneWidget);
2537
expect(
@@ -32,6 +44,10 @@ class AppBarPage {
3244
await $(getStartedBtn).tap(settleTimeout: Time.short.duration);
3345
}
3446

47+
Future<bool> getStartedBtnExists() async {
48+
return $(getStartedBtn).exists;
49+
}
50+
3551
Future<void> getStartedBtnIsVisible() async {
3652
expect($(getStartedBtn), findsOneWidget);
3753
expect($(getStartedBtn).$(Text).text, (await t()).getStarted);
@@ -43,10 +59,12 @@ class AppBarPage {
4359

4460
Future<void> looksAsExpectedForVisitor() async {
4561
await getStartedBtnIsVisible();
62+
await visitorBtnIsVisible();
4663
}
4764

4865
Future<void> looksAsExpectedForVisitorOnboardingInProgress() async {
4966
await finishAccountCreationBtnIsVisible();
67+
await visitorBtnIsVisible();
5068
}
5169

5270
Future<void> sessionAccountPopupMenuAvatarIsVisible() async {
@@ -57,8 +75,8 @@ class AppBarPage {
5775
await $(spacesDrawerButton).waitUntilVisible().tap();
5876
}
5977

60-
Future<void> spacesDrawerButtonExists({bool? reverse = false}) async {
61-
expect($(spacesDrawerButton).exists, !reverse!);
78+
Future<void> spacesDrawerButtonExists({bool reverse = false}) async {
79+
expect($(spacesDrawerButton).exists, !reverse);
6280
}
6381

6482
Future<void> unlockBtnClick() async {
@@ -68,4 +86,8 @@ class AppBarPage {
6886
Future<void> unlockBtnIsVisible() async {
6987
expect($(unlockBtn), findsOneWidget);
7088
}
89+
90+
Future<void> visitorBtnIsVisible() async {
91+
expect($(visitorBtn), findsOneWidget);
92+
}
7193
}

catalyst_voices/apps/voices/integration_test/pageobject/common_page.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:patrol_finders/patrol_finders.dart';
33

44
class CommonPage {
5-
late PatrolTester $;
5+
final PatrolTester $;
66

77
final decorData = const Key('DecoratorData');
88
final decorIconBefore = const Key('DecoratorIconBefore');
@@ -16,5 +16,6 @@ class CommonPage {
1616
final errorRetryBtn = const Key('ErrorRetryBtn');
1717
final buttonFilledType = const Key('ButtonFilled');
1818
final buttonTextType = const Key('ButtonText');
19+
1920
CommonPage(this.$);
2021
}

catalyst_voices/apps/voices/integration_test/pageobject/discovery/campaign_categories_section.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import '../../utils/translations_utils.dart';
66
import '../discovery_page.dart';
77

88
class CampaignCategoriesSection {
9-
late PatrolTester $;
9+
final PatrolTester $;
1010

1111
final categoriesRoot = const Key('CampaignCategoriesStateSelector');
1212
final categoriesTitle = const Key('CampaignCategoriesTitle');
@@ -22,10 +22,11 @@ class CampaignCategoriesSection {
2222
final categoryDetailsButton = const Key('CategoryDetailsBtn');
2323
final viewProposalsButton = const Key('ViewProposalsBtn');
2424
final categoriesLoadingError = const Key('CampaignCategoriesError');
25+
2526
CampaignCategoriesSection(this.$);
2627

2728
Future<void> categoriesAreRenderedCorrectly() async {
28-
for (var i = 0; i < 6; i++) {
29+
for (var i = 0; i < 4; i++) {
2930
try {
3031
$(categoriesRoot).$(campaignCategories).at(i).$(description).visible;
3132
} catch (e) {

catalyst_voices/apps/voices/integration_test/pageobject/discovery/campaign_hero_section_page.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import 'package:patrol_finders/patrol_finders.dart';
55
import '../../utils/translations_utils.dart';
66

77
class CampaignHeroSection {
8-
late PatrolTester $;
8+
final PatrolTester $;
9+
910
final heroBackgroundVideo = const Key('HeroBackgroundVideo');
1011
final campaignBriefTitle = const Key('CampaignBriefTitle');
1112
final campaignBriefDescription = const Key('CampaignBriefDescription');
1213
final viewProposalsButton = const Key('ViewProposalsBtn');
1314
final unlockBtn = const Key('UnlockButton');
1415
final loadingError = const Key('ErrorIndicator');
1516
final campaignHeroSectionRoot = const Key('CampaignHeroSection');
17+
1618
CampaignHeroSection(this.$);
1719

1820
Future<void> campaignBriefDescriptionIsRenderedCorrectly() async {

catalyst_voices/apps/voices/integration_test/pageobject/discovery/current_campaign_selector_page.dart

Lines changed: 14 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ import '../../utils/translations_utils.dart';
88
import '../discovery_page.dart';
99

1010
class CurrentCampaignSection {
11-
late PatrolTester $;
11+
final PatrolTester $;
1212

13-
final currentCampaignRoot = const Key('CurrentCampaignRoot');
1413
final title = const Key('CurrentCampaignTitle');
1514
final subtitle = const Key('Subtitle');
1615
final description = const Key('Description');
@@ -24,12 +23,13 @@ class CurrentCampaignSection {
2423
final timelineCard = const Key('TimelineCard');
2524
final campaignTimelineComponent = const Key('CampaignTimeline');
2625
final timelineCardTitle = const Key('TimelineCardTitle');
27-
final timelineCardDate = const Key('TimelineCardDate');
2826
final currentCampaignLoadingError = const Key('CurrentCampaignError');
27+
2928
CurrentCampaignSection(this.$);
3029

3130
Future<void> campaignDetailsAreRenderedCorrectly() async {
32-
await $(fundsDetailCard).$(fundsDetailAskRangeMax).$(#Title).scrollTo();
31+
await $(fundsDetailCard).scrollTo();
32+
3333
expect(
3434
$(fundsDetailCard).$(fundsDetailBudget).$(#Title).text,
3535
(await t()).campaignTreasury,
@@ -54,34 +54,16 @@ class CurrentCampaignSection {
5454
$(fundsDetailCard).$(fundsDetailRequested).$(#Funds).text!.isNotEmpty,
5555
isTrue,
5656
);
57-
expect(
58-
$(fundsDetailCard).$(fundsDetailAskRangeMax).$(#Title).text,
59-
(await t()).maximumAsk,
60-
);
61-
expect(
62-
$(fundsDetailCard).$(fundsDetailAskRangeMax).$(#Value).text!.isNotEmpty,
63-
isTrue,
64-
);
65-
expect(
66-
$(fundsDetailCard).$(fundsDetailAskRangeMax).$(#Value).text!.isNotEmpty,
67-
isTrue,
68-
);
69-
await $(currentCampaignRoot).$(ideaSubTitle).scrollTo(step: 150);
70-
expect(
71-
$(currentCampaignRoot).$(ideaSubTitle).text,
72-
(await t()).ideaJourney,
73-
);
74-
final descriptionText = $.tester
75-
.widget<MarkdownBody>(
76-
$(currentCampaignRoot).$(ideaDescription).$(MarkdownBody),
77-
)
78-
.data;
57+
58+
await $(ideaSubTitle).scrollTo(step: 150);
59+
expect($(ideaSubTitle).text, (await t()).ideaJourney);
60+
final descriptionText = $.tester.widget<MarkdownBody>($(ideaDescription).$(MarkdownBody)).data;
7961
final textToMatch = (await t())
8062
.ideaJourneyDescription(VoicesConstants.campaignTimeline)
8163
.split('#### ')[1]
8264
.split('[fund timeline]')[0];
8365
expect(descriptionText.indexOf(textToMatch), greaterThanOrEqualTo(1));
84-
expect($(currentCampaignRoot).$(timelineCard), findsExactly(5));
66+
expect($(timelineCard), findsExactly(6));
8567
}
8668

8769
Future<void> descriptionIsRenderedCorrectly() async {
@@ -98,35 +80,23 @@ class CurrentCampaignSection {
9880
}
9981

10082
Future<void> subtitleIsRenderedCorrectly() async {
101-
expect($(subtitle).text?.startsWith('Catalyst Fund '), true);
83+
expect($(subtitle).text?.startsWith('Catalyst Fund'), true);
10284
}
10385

10486
Future<void> timelineCardsDataIsRendered() async {
10587
await descriptionIsRenderedCorrectly();
10688
await DiscoveryPage($).loadRetryOnError(currentCampaignLoadingError);
107-
await $(currentCampaignRoot).$(timelineCard).at(0).$(timelineCardDate).scrollTo(step: 150);
108-
for (var i = 0; i < 5; i++) {
89+
90+
for (var i = 0; i < 6; i++) {
10991
final cardTitle = $(campaignTimelineComponent).$(timelineCard).at(i).$(timelineCardTitle);
11092
await $.tester.dragUntilVisible(
11193
cardTitle,
11294
$(campaignTimelineComponent).$(SingleChildScrollView),
11395
const Offset(10, 0),
11496
);
97+
await $(timelineCard).at(i).tap();
11598
expect(
116-
$(currentCampaignRoot).$(timelineCard).at(i).$(AnimatedSwitcher).$(Text),
117-
findsNothing,
118-
);
119-
await $(currentCampaignRoot).$(timelineCard).at(i).tap();
120-
expect(
121-
$(currentCampaignRoot).$(timelineCard).at(i).$(timelineCardTitle).text,
122-
isNotEmpty,
123-
);
124-
expect(
125-
$(currentCampaignRoot).$(timelineCard).at(i).$(timelineCardDate).text,
126-
isNotEmpty,
127-
);
128-
expect(
129-
$(currentCampaignRoot).$(timelineCard).at(i).$(AnimatedSwitcher).$(Text).text,
99+
$(timelineCard).at(i).$(timelineCardTitle).text,
130100
isNotEmpty,
131101
);
132102
}

catalyst_voices/apps/voices/integration_test/pageobject/discovery/how_it_works_section_page.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:patrol_finders/patrol_finders.dart';
55
import '../../utils/translations_utils.dart';
66

77
class HowItWorksSection {
8-
late PatrolTester $;
8+
final PatrolTester $;
99

1010
final title = const Key('HowItWorksTitle');
1111
final collaborateAvatar = const Key('collaborateAvatar');
@@ -19,6 +19,7 @@ class HowItWorksSection {
1919
final followDescription = const Key('followDescription');
2020
final loadingError = const Key('ErrorIndicator');
2121
final howItWorksRoot = const Key('HowItWorks');
22+
2223
HowItWorksSection(this.$);
2324

2425
Future<void> collaborateAvatarIsRenderedCorrectly() async {

0 commit comments

Comments
 (0)