Skip to content

Commit

Permalink
Merge pull request #212 from privacybydesign/notifications-ui
Browse files Browse the repository at this point in the history
feat: credential status notifications
  • Loading branch information
sjoerdlmkns authored Aug 2, 2023
2 parents 258f7f3 + 2b28595 commit 4e40ff1
Show file tree
Hide file tree
Showing 27 changed files with 1,136 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Added
- Credential status notifications
### Fixed
- Voice over and accessibility tags are not correctly set on the PIN screen
- Required update screen refers to iTunes Store instead of Apple App Store
Expand Down
6 changes: 6 additions & 0 deletions assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,8 @@
"explanation": "Everything remained the same under the hood, you can log in with your old PIN code."
},
"notifications": {
"title": "Notifications",
"empty": "No notifications",
"credential_status": {
"revoked": {
"title": "Data revoked",
Expand All @@ -610,6 +612,10 @@
"title": "Data expiring soon",
"message": "This data is expiring soon: {credentialName}"
}
},
"bell": {
"new_notifications": "Notifications bell - New notifications",
"no_new_notifications": "Notifications bell - No new notifications"
}
}
}
8 changes: 7 additions & 1 deletion assets/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,9 @@
"header": "IRMA heeft een nieuwe naam en een nieuw uiterlijk gekregen: Yivi",
"explanation": "Onder de motorkap is alles hetzelfde gebleven, je kunt gewoon inloggen met je oude PIN-code."
},
"nofitifcations": {
"notifications": {
"title": "Notificaties",
"empty": "Geen notificaties",
"credential_status": {
"revoked": {
"title": "Gegevens ingetrokken",
Expand All @@ -610,6 +612,10 @@
"title": "Gegevens verlopen bijna",
"message": "Deze gegevens verlopen bijna: {credentialName}"
}
},
"bell": {
"new_notifications": "Notificatiebel - Nieuwe notificaties",
"no_new_notifications": "Notificatiebel - Geen nieuwe notificaties"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:irmamobile/src/screens/data/credentials_detail_screen.dart';
import 'package:irmamobile/src/screens/notifications/widgets/notification_bell.dart';
import 'package:irmamobile/src/screens/notifications/widgets/notification_card.dart';

import 'package:irmamobile/src/screens/session/disclosure/widgets/disclosure_permission_choices_screen.dart';
import 'package:irmamobile/src/widgets/credential_card/irma_credential_card.dart';
Expand Down Expand Up @@ -44,7 +47,6 @@ Future<void> revocationTest(WidgetTester tester, IntegrationTestIrmaBinding irma
);

await revokeCredential('irma-demo.MijnOverheid.root', revocationKey);

await irmaBinding.repository.startTestSession('''
{
"@context": "https://irma.app/ld/request/disclosure/v2",
Expand Down Expand Up @@ -76,21 +78,45 @@ Future<void> revocationTest(WidgetTester tester, IntegrationTestIrmaBinding irma
find.text('Close'),
);

//Go to the data tab
await tester.tapAndSettle(find.byKey(const Key('nav_button_data')));
// The NotificationBell should be findable in the app bar
final notificationBellFinder = find.byType(NotificationBell);
expect(notificationBellFinder, findsOneWidget);
await tester.tapAndSettle(notificationBellFinder);

// Tap the card with the text Demo Root
final demoRootFinder = find.text('Demo Root');
await tester.scrollUntilVisible(demoRootFinder, 100);
await tester.tapAndSettle(demoRootFinder);
// Now pull to refresh and expect a notification card
await tester.drag(find.byType(RefreshIndicator), const Offset(0, 500));
await tester.pumpAndSettle();

// Find the credential card
final credentialCardFinder = find.byType(IrmaCredentialCard).first;
expect(credentialCardFinder, findsOneWidget);
final notificationCardsFinder = find.byType(NotificationCard);
expect(notificationCardsFinder, findsOneWidget);

await _evaluateDemoCredentialCard(
final notificationCardFinder = notificationCardsFinder.first;
await evaluateNotificationCard(
tester,
notificationCardFinder,
title: 'Data revoked',
content: 'Demo MijnOverheid.nl has revoked this data: Demo Root',
read: false,
);

// Tap the notification card to open the credential detail screen
await tester.tapAndSettle(notificationCardFinder);

// Expect the credential detail screen
final credentialDetailScreenFinder = find.byType(CredentialsDetailScreen);
expect(credentialDetailScreenFinder, findsOneWidget);

// Expect the actual credential card
final credentialCardsFinder = find.byType(IrmaCredentialCard);
expect(credentialCardsFinder, findsOneWidget);

final credentialCardFinder = credentialCardsFinder.first;
await evaluateCredentialCard(
tester,
credentialCardFinder,
credentialName: 'Demo Root',
issuerName: 'Demo MijnOverheid.nl',
attributes: {'BSN': '12345'},
isRevoked: true,
);

Expand Down
53 changes: 50 additions & 3 deletions integration_test/helpers/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'package:irmamobile/app.dart';
import 'package:irmamobile/main.dart';
import 'package:irmamobile/src/data/irma_repository.dart';
import 'package:irmamobile/src/screens/home/home_tab.dart';
import 'package:irmamobile/src/screens/notifications/bloc/notifications_bloc.dart';
import 'package:irmamobile/src/screens/notifications/widgets/notification_card.dart';
import 'package:irmamobile/src/screens/session/widgets/issuance_permission.dart';
import 'package:irmamobile/src/widgets/credential_card/irma_credential_card.dart';
import 'package:irmamobile/src/widgets/credential_card/irma_credential_card_attribute_list.dart';
Expand Down Expand Up @@ -38,9 +40,15 @@ Future<void> enterPin(WidgetTester tester, String pin) async {
await tester.pumpAndSettle(const Duration(milliseconds: 1500));
}

Future<void> pumpIrmaApp(WidgetTester tester, IrmaRepository repo, [Locale? defaultLanguage]) async {
Future<void> pumpIrmaApp(
WidgetTester tester,
IrmaRepository repo, [
Locale? defaultLanguage,
NotificationsBloc? notificationsBloc,
]) async {
await tester.pumpWidgetAndSettle(IrmaApp(
repository: repo,
notificationsBloc: notificationsBloc ?? NotificationsBloc(repo: repo),
defaultLanguage: defaultLanguage ?? const Locale('en', 'EN'),
));

Expand All @@ -53,8 +61,9 @@ Future<void> pumpIrmaApp(WidgetTester tester, IrmaRepository repo, [Locale? defa
}

// Pump a new app and unlock it
Future<void> pumpAndUnlockApp(WidgetTester tester, IrmaRepository repo, [Locale? locale]) async {
await pumpIrmaApp(tester, repo, locale);
Future<void> pumpAndUnlockApp(WidgetTester tester, IrmaRepository repo,
[Locale? locale, NotificationsBloc? notificationsBloc]) async {
await pumpIrmaApp(tester, repo, locale, notificationsBloc);
await unlock(tester);
}

Expand Down Expand Up @@ -341,3 +350,41 @@ Future<void> evaluateCredentialCard(
}
}
}

Future<void> evaluateNotificationCard(
WidgetTester tester,
Finder notificationCardFinder, {
String? title,
String? content,
bool? read,
}) async {
expect(notificationCardFinder, findsOneWidget);

if (title != null) {
expect(
find.descendant(
of: notificationCardFinder,
matching: find.text(title),
),
findsOneWidget,
);
}

if (content != null) {
expect(
find.descendant(
of: notificationCardFinder,
matching: find.text(content),
),
findsOneWidget,
);
}

if (read != null) {
final notificationCardWidget = notificationCardFinder.evaluate().single.widget as NotificationCard;
expect(
notificationCardWidget.notification.read,
read,
);
}
}
9 changes: 9 additions & 0 deletions integration_test/helpers/issuance_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ import 'package:flutter_test/flutter_test.dart';
import '../irma_binding.dart';
import 'helpers.dart';

Future<void> issueIrmaTubeMember(
WidgetTester tester,
IntegrationTestIrmaBinding irmaBinding,
) =>
issueCredentials(tester, irmaBinding, {
'irma-demo.IRMATube.member.type': 'USER',
'irma-demo.IRMATube.member.id': '123123',
});

Future<void> issueEmailAddress(
WidgetTester tester,
IntegrationTestIrmaBinding irmaBinding,
Expand Down
Loading

0 comments on commit 4e40ff1

Please sign in to comment.