Skip to content

Commit

Permalink
feat(pin_code_widget): Detail view, Edit or Delete PIN Code(s) (#55)
Browse files Browse the repository at this point in the history
* feat(pin_code_widget): tap on existing pin code to view details

* feat(pin_code_provider): methods to update or delete a pin code

* refactor(pin_code_detail): style Delete Button

* refactor(pin_code_detail): obscure PIN Code field

* refactor(pin_code_widget): refactor text input validation

* refactor(pin_code_slim_widget): call updatePinCode Mutation if editing existing PIN Code

* feat(pin_code_detail): on delete button press, show dialog to confirm

* test(pin_code_widget): tests around deleting a PIN Code

* test(pin_code_widget): fix code and test to dismiss dialog after deleting PIN Code

* feat(pin_code_detail): no saving allowed if no changes were made

* refactor(pin_code_list): fix styles for list view items

* refactor(pin_code_detail): eye icon to display or obscure pin code

* chore(pin_code_widget): update styles according to figma designs

* build(pubspec.yaml): update yonomi_platform_sdk to v5.2.0
  • Loading branch information
ses110 committed Sep 28, 2022
1 parent 7416c1a commit 1c50e6a
Show file tree
Hide file tree
Showing 11 changed files with 584 additions and 75 deletions.
39 changes: 39 additions & 0 deletions lib/providers/pin_code_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import 'package:yonomi_platform_sdk/yonomi-sdk.dart';
typedef SendCreatePinCodeMethod = Future<void> Function(
Request request, String id, String pinCode, String pinCodeName);

typedef SendUpdatePinCodeMethod = Future<void> Function(
Request request, String id, String pinCode, String pinCodeName);

typedef SendDeletePinCodeMethod = Future<void> Function(
Request request, String id, String pinCode);

class PinCodeProvider extends DeviceProvider {
static const _DEFAULT_DISPLAY_NAME = 'PIN_CODE';

Expand Down Expand Up @@ -34,6 +40,39 @@ class PinCodeProvider extends DeviceProvider {
getDetails: getDetails);
}

/// Run the "makeUpdatePinCodeActionRequest" mutation on this device
///
/// @param pinCode the pin code
/// @param pinCodeName the name for the pin code
/// @throws ServerException for any errors returned by the platform
Future<void> sendUpdatePinCode(String pinCode, String pinCodeName,
{GetDeviceDetailsMethod getDetails = DevicesRepository.getDeviceDetails,
SendUpdatePinCodeMethod sendUpdatePinCodeMethod =
PinCodeRepository.sendUpdatePinCodeAction}) async {
return performAction<List<PinCodeCredential>>(
[...?getPinCodeCredentials, PinCodeCredential(pinCodeName, pinCode)],
() => getPinCodeCredentials,
() => sendUpdatePinCodeMethod(
_request, this._deviceId, pinCode, pinCodeName),
getDetails: getDetails);
}

/// Run the "makeDeletePinCodeActionRequest" mutation on this device
///
/// @param pinCode the pin code
/// @param pinCodeName the name for the pin code
/// @throws ServerException for any errors returned by the platform
Future<void> sendDeletePinCode(String pinCode, String pinCodeName,
{GetDeviceDetailsMethod getDetails = DevicesRepository.getDeviceDetails,
SendDeletePinCodeMethod sendDeletePinCodeMethod =
PinCodeRepository.sendDeletePinCodeAction}) async {
return performAction<List<PinCodeCredential>>(
[...?getPinCodeCredentials, PinCodeCredential(pinCodeName, pinCode)],
() => getPinCodeCredentials,
() => sendDeletePinCodeMethod(_request, this._deviceId, pinCode),
getDetails: getDetails);
}

PinCodeTrait? getPinCodeTrait() {
return trait<PinCodeTrait>() as PinCodeTrait?;
}
Expand Down
236 changes: 187 additions & 49 deletions lib/traits/slim/pin_code_slim_widget.dart

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions lib/ui/color_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ class ColorConstants {

static const Color pinCodeListBodyBg = Color(0xFFE8EAEE);

static const Color PIN_CODE_DELETE_BUTTON_RED = Color(0xFFDC7E91);

static const Color PIN_CODE_DELETE_BUTTON_TEXT_RED = Color(0xFFDC3646);

static const Color pinCodeDetailCheckColor = Color(0xFF70C7C0);

static const Color pinCodeDetailCheckDisabledColor = Color(0xFFD5D5D5);

static const Color pinCodeDetailBodyBg = Color(0xFFE8EAEE);

static const Color pinCodeDetailTextFieldLabelText = Color(0xFF5A626C);
Expand Down
29 changes: 29 additions & 0 deletions lib/ui/string_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,42 @@ class StringConstants {
static const String AN_ERROR_OCCURRED = 'An error occurred.';
static const String DEVICE_IS_JAMMED = 'The device is jammed.';

static const String PIN_CODE_DELETE_ALERT_CANCEL = 'Cancel';

static const String PIN_CODE_DELETE_ALERT_MSG_TEXT =
'Are you sure you wish to delete this PIN Code?';

static const String PIN_CODE_DELETE_ALERT_OK = 'OK';

static const String PIN_CODE_DELETE_ALERT_TITLE = 'Delete PIN Code';

static const String PIN_CODES_DELETE_BUTTON_TEXT = 'Delete PIN Code';

static const String PIN_CODES_EDIT_PIN_CODE = 'Edit PIN Code';

static const String PIN_CODES_INPUT_VALID_RANGE_MIN =
'Please input a value more than the minimum valid range';

static const String PIN_CODES_INPUT_VALID_RANGE_MAX =
'Please input a value less than the maximum valid range';

static const String PIN_CODES_LIST_SCREEN_TITLE = 'PIN Codes';

static const String PIN_CODES_MANAGE_PIN_CODES = 'Manage PIN Codes';

static const String PIN_CODES_NEW_PIN_CODE = 'New PIN Code';

static const String PIN_CODES_NO_CHANGES_MADE = 'No changes were made';

static const String PIN_CODES_NO_PIN_CODES = 'No PIN Codes Found';

static const String PIN_CODES_PIN_CODE = 'PIN Code';

static const String PIN_CODES_PIN_CODE_NAME = 'PIN Code Name';

static const String PIN_CODES_PIN_CODE_SETTINGS = 'PIN Code Settings';

static const String PIN_CODES_PLEASE_ENTER_TEXT = 'Please enter some text';

static const String PIN_CODES_SAVED_CHANGES = 'Saved changes';
}
27 changes: 21 additions & 6 deletions lib/ui/widget_style_constants.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:yonomi_device_widgets/ui/color_constants.dart';

class WidgetStyleConstants {
WidgetStyleConstants._(); // coverage:ignore-line
Expand Down Expand Up @@ -47,20 +48,34 @@ class WidgetStyleConstants {

static const Color jammedStateTextColor = Colors.white;

static ButtonStyle pinCodeDeleteButtonStyle = OutlinedButton.styleFrom(
minimumSize: Size.fromHeight(60),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
side: BorderSide(
color: ColorConstants.PIN_CODE_DELETE_BUTTON_RED, width: 2.0),
);

static const TextStyle pinCodeDeleteButtonTextStyle = TextStyle(
color: ColorConstants.PIN_CODE_DELETE_BUTTON_TEXT_RED,
fontWeight: FontWeight.w500,
fontSize: 18.0);

static const Color pinCodeListTitleColor = Color(0xFF5E6578);

static const Color pinCodeListItemColor = Color(0xFF4DA49F);

static const TextStyle pinCodeListItemStyle =
TextStyle(color: WidgetStyleConstants.pinCodeListItemColor);
static const TextStyle pinCodeListItemStyle = TextStyle(
color: WidgetStyleConstants.pinCodeListItemColor, fontSize: 16.0);

static const TextStyle pinCodeListTitleStyle = TextStyle(
color: WidgetStyleConstants.pinCodeListTitleColor,
fontWeight: FontWeight.w900,
fontSize: 18.0);
fontWeight: FontWeight.w500,
fontSize: 22.0);

static const TextStyle pinCodeDetailTitleStyle = TextStyle(
color: WidgetStyleConstants.pinCodeListTitleColor,
fontWeight: FontWeight.w900,
fontSize: 16.0);
fontWeight: FontWeight.w500,
fontSize: 18.0);
}
34 changes: 33 additions & 1 deletion test/mixins/pin_code_testing.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class MockPinCodeProvider extends _i1.Mock implements _i2.PinCodeProvider {
_i2.SendCreatePinCodeMethod? sendCreatePinCodeMethod =
_i7.PinCodeRepository.sendCreatePinCodeAction}) =>
(super.noSuchMethod(
Invocation.method(#sendAddPinCode, [
Invocation.method(#sendCreatePinCode, [
pinCode,
pinCodeName
], {
Expand All @@ -79,6 +79,38 @@ class MockPinCodeProvider extends _i1.Mock implements _i2.PinCodeProvider {
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i4.Future<void>);
@override
_i4.Future<void> sendUpdatePinCode(String? pinCode, String? pinCodeName,
{_i5.GetDeviceDetailsMethod? getDetails =
_i6.DevicesRepository.getDeviceDetails,
_i2.SendUpdatePinCodeMethod? sendUpdatePinCodeMethod =
_i7.PinCodeRepository.sendUpdatePinCodeAction}) =>
(super.noSuchMethod(
Invocation.method(#sendUpdatePinCode, [
pinCode,
pinCodeName
], {
#getDetails: getDetails,
#sendUpdatePinCodeMethod: sendUpdatePinCodeMethod
}),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i4.Future<void>);
@override
_i4.Future<void> sendDeletePinCode(String? pinCode, String? pinCodeName,
{_i5.GetDeviceDetailsMethod? getDetails =
_i6.DevicesRepository.getDeviceDetails,
_i2.SendDeletePinCodeMethod? sendDeletePinCodeMethod =
_i7.PinCodeRepository.sendDeletePinCodeAction}) =>
(super.noSuchMethod(
Invocation.method(#sendDeletePinCode, [
pinCode,
pinCodeName
], {
#getDetails: getDetails,
#sendDeletePinCodeMethod: sendDeletePinCodeMethod
}),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i4.Future<void>);
@override
_i4.Future<void> fetchData(
{_i5.GetDeviceDetailsMethod? getDetails =
_i6.DevicesRepository.getDeviceDetails}) =>
Expand Down
58 changes: 57 additions & 1 deletion test/providers/pin_code_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ class SendCreatePinCodeMethod extends Mock {
Request request, String id, String pinCode, String pinCodeName);
}

class SendUpdatePinCodeMethod extends Mock {
Future<void> call(
Request request, String id, String pinCode, String pinCodeName);
}

class SendDeletePinCodeMethod extends Mock {
Future<void> call(Request request, String id, String pinCode);
}

class PinCodeTraitProviderTest with DeviceTesting, PinCodeTesting {
MockGetDeviceDetailsMethod getMockDeviceDetailsMethod(
Request request, String deviceId) {
Expand All @@ -37,7 +46,12 @@ class PinCodeTraitProviderTest with DeviceTesting, PinCodeTesting {
}
}

@GenerateMocks([GetDeviceDetailsMethod, SendCreatePinCodeMethod])
@GenerateMocks([
GetDeviceDetailsMethod,
SendCreatePinCodeMethod,
SendUpdatePinCodeMethod,
SendDeletePinCodeMethod
])
void main() {
final pinCodeProviderTest = PinCodeTraitProviderTest();

Expand Down Expand Up @@ -95,5 +109,47 @@ void main() {
verify(mockSendCreatePinCodeMethod(request, deviceId, 'Admin', '5678'))
.called(greaterThan(0));
});

test('Calling SendUpdatePinCodeMethod calls repository method', () async {
Request request = Request("", {});
String deviceId = 'aDeviceId';

final GetDeviceDetailsMethod mockDeviceDetailsMethod =
pinCodeProviderTest.getMockDeviceDetailsMethod(request, deviceId);

final mockSendUpdatePinCodeMethod = MockSendUpdatePinCodeMethod();

PinCodeProvider pinCodeProvider = await PinCodeProvider(request, deviceId,
getDetails: mockDeviceDetailsMethod);

await pinCodeProvider.sendUpdatePinCode('Admin', '5678',
getDetails: mockDeviceDetailsMethod,
sendUpdatePinCodeMethod: mockSendUpdatePinCodeMethod);

verify(mockDeviceDetailsMethod(request, deviceId)).called(greaterThan(0));
verify(mockSendUpdatePinCodeMethod(request, deviceId, 'Admin', '5678'))
.called(greaterThan(0));
});

test('Calling SendDeletePinCodeMethod calls repository method', () async {
Request request = Request("", {});
String deviceId = 'aDeviceId';

final GetDeviceDetailsMethod mockDeviceDetailsMethod =
pinCodeProviderTest.getMockDeviceDetailsMethod(request, deviceId);

final mockSendDeletePinCodeMethod = MockSendDeletePinCodeMethod();

PinCodeProvider pinCodeProvider = await PinCodeProvider(request, deviceId,
getDetails: mockDeviceDetailsMethod);

await pinCodeProvider.sendDeletePinCode('5678', 'Admin',
getDetails: mockDeviceDetailsMethod,
sendDeletePinCodeMethod: mockSendDeletePinCodeMethod);

verify(mockDeviceDetailsMethod(request, deviceId)).called(greaterThan(0));
verify(mockSendDeletePinCodeMethod(request, deviceId, '5678'))
.called(greaterThan(0));
});
});
}
38 changes: 38 additions & 0 deletions test/providers/pin_code_provider_test.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,41 @@ class MockSendCreatePinCodeMethod extends _i1.Mock
@override
String toString() => super.toString();
}

/// A class which mocks [SendUpdatePinCodeMethod].
///
/// See the documentation for Mockito's code generation for more information.
class MockSendUpdatePinCodeMethod extends _i1.Mock
implements _i3.SendUpdatePinCodeMethod {
MockSendUpdatePinCodeMethod() {
_i1.throwOnMissingStub(this);
}

@override
_i4.Future<void> call(_i2.Request? request, String? id, String? pinCode,
String? pinCodeName) =>
(super.noSuchMethod(
Invocation.method(#call, [request, id, pinCode, pinCodeName]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i4.Future<void>);
@override
String toString() => super.toString();
}

/// A class which mocks [SendDeletePinCodeMethod].
///
/// See the documentation for Mockito's code generation for more information.
class MockSendDeletePinCodeMethod extends _i1.Mock
implements _i3.SendDeletePinCodeMethod {
MockSendDeletePinCodeMethod() {
_i1.throwOnMissingStub(this);
}

@override
_i4.Future<void> call(_i2.Request? request, String? id, String? pinCode) =>
(super.noSuchMethod(Invocation.method(#call, [request, id, pinCode]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i4.Future<void>);
@override
String toString() => super.toString();
}
2 changes: 1 addition & 1 deletion test/traits/brightness_widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ main() {
expect(find.byType(CircularProgressIndicator), findsOneWidget);
});

testWidgets('When battery widget is in error, should show error icon',
testWidgets('When brightness widget is in error, should show error icon',
(WidgetTester tester) async {
final mockBrightnessProvider =
test.mockBrightnessProvider(brightnessDevice);
Expand Down
Loading

0 comments on commit 1c50e6a

Please sign in to comment.