From eca7d00d16f11fbd8ac538c90f7b2f7ce9d31b5c Mon Sep 17 00:00:00 2001 From: ashuntu Date: Tue, 17 Dec 2024 11:37:56 -0600 Subject: [PATCH] Convert custom Either wrapper to just an Either --- .../subscribe_now/subscribe_now_model.dart | 34 ++++++------------- .../subscribe_now/subscribe_now_page.dart | 4 +-- .../subscribe_now/subscribe_now_widgets.dart | 6 ++-- .../subscribe_now_model_test.dart | 31 +++++++++++++++++ .../subscribe_now_widgets_test.dart | 27 --------------- 5 files changed, 46 insertions(+), 56 deletions(-) diff --git a/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_model.dart b/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_model.dart index 3b0af038d..2d9a2dbba 100644 --- a/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_model.dart +++ b/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_model.dart @@ -10,9 +10,11 @@ class SubscribeNowModel extends ChangeNotifier { final AgentApiClient client; P4wMsStore store; - final _token = ProTokenValue(); - ProTokenValue get token => _token; - bool get canSubmit => token.token != null; + Either _token = const Either.left(TokenError.empty); + ProToken? get token => _token.orNull(); + TokenError? get tokenError => + _token.fold(ifLeft: (e) => e, ifRight: (_) => null); + bool get canSubmit => token != null; /// Returns true if the environment variable 'UP4W_ALLOW_STORE_PURCHASE' has been set. /// Since this reading won't change during the app lifetime, even if the user changes @@ -52,29 +54,13 @@ class SubscribeNowModel extends ChangeNotifier { } } - void tokenUpdate(String token) async { - _token.update(token); + void updateToken(String raw) { + _token = ProToken.create(raw); notifyListeners(); } -} - -/// A [ProToken] with validation. -/// -/// Similar to a [EitherValueNotifier], without the [ValueNotifier]. -class ProTokenValue { - ProTokenValue() : either = const Either.left(TokenError.empty); - - Either either; - ProToken? get token => either.orNull(); - String? get value => either.orNull()?.value; - TokenError? get error => either.fold(ifLeft: (e) => e, ifRight: (_) => null); - bool get hasError => either.isLeft; - void update(String token) { - either = ProToken.create(token); - } - - void clear() { - either = const Either.right(null); + void clearToken() { + _token = const Either.right(null); + notifyListeners(); } } diff --git a/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_page.dart b/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_page.dart index 4a4f64013..4d208ae99 100644 --- a/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_page.dart +++ b/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_page.dart @@ -94,8 +94,8 @@ class SubscribeNowPage extends StatelessWidget { } void trySubmit(SubscribeNowModel model) { - model.applyProToken(model.token.token!).then(onSubscriptionUpdate); - model.token.clear(); + model.applyProToken(model.token!).then(onSubscriptionUpdate); + model.clearToken(); controller.clear(); } diff --git a/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_widgets.dart b/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_widgets.dart index 0c27e5eb6..7dbc315c1 100644 --- a/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_widgets.dart +++ b/gui/packages/ubuntupro/lib/pages/subscribe_now/subscribe_now_widgets.dart @@ -60,11 +60,11 @@ class ProTokenInputField extends StatelessWidget { controller: controller, decoration: InputDecoration( label: Text(lang.tokenInputHint), - error: model.token.error?.localize(lang) != null + error: model.tokenError?.localize(lang) != null ? Padding( padding: const EdgeInsets.only(top: 4), child: Text( - model.token.error!.localize(lang)!, + model.tokenError!.localize(lang)!, style: theme.textTheme.bodySmall!.copyWith( color: YaruColors.of(context).error, ), @@ -72,7 +72,7 @@ class ProTokenInputField extends StatelessWidget { ) : null, ), - onChanged: model.tokenUpdate, + onChanged: model.updateToken, onSubmitted: (_) => onSubmit?.call(), ), ], diff --git a/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_model_test.dart b/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_model_test.dart index 7d1f2ccd9..dc4214a5c 100644 --- a/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_model_test.dart +++ b/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_model_test.dart @@ -16,6 +16,37 @@ import 'subscribe_now_model_test.mocks.dart'; @GenerateMocks([AgentApiClient]) void main() { + group('token', () { + final client = MockAgentApiClient(); + + test('errors', () async { + final model = SubscribeNowModel(client); + expect(model.canSubmit, isFalse); + + model.updateToken(''); + expect(model.token, isNull); + expect(model.tokenError, TokenError.empty); + expect(model.canSubmit, isFalse); + + for (final badToken in tks.invalidTokens) { + model.updateToken(badToken); + expect(model.token, isNull); + expect(model.tokenError, TokenError.invalid); + expect(model.canSubmit, isFalse); + } + }); + + test('valid', () async { + final model = SubscribeNowModel(client); + expect(model.canSubmit, isFalse); + + model.updateToken(tks.good); + expect(model.token, isNotNull); + expect(model.tokenError, isNull); + expect(model.canSubmit, isTrue); + }); + }); + group('purchase', () { const pluginChannel = MethodChannelP4wMsStore.methodChannel; final pluginMessenger = diff --git a/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_widgets_test.dart b/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_widgets_test.dart index dd67a73fe..68550ea2a 100644 --- a/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_widgets_test.dart +++ b/gui/packages/ubuntupro/test/pages/subcribe_now/subscribe_now_widgets_test.dart @@ -29,33 +29,6 @@ void main() { expect(launcher.launched, isTrue); }); - group('pro token value', () { - test('errors', () async { - final value = ProTokenValue(); - - value.update(''); - expect(value.error, TokenError.empty); - - for (final token in tks.invalidTokens) { - value.update(token); - expect(value.error, TokenError.invalid); - } - }); - test('accessors on success', () { - final value = ProTokenValue(); - final tokenInstance = ProToken.create(tks.good).orNull(); - - value.update(tks.good); - - expect(value.hasError, isFalse); - expect(value.error, isNull); - expect(value.value, tks.good); - expect(value.value, tks.good); - expect(value.token, tokenInstance); - expect(value.either, equals(ProToken.create(tks.good))); - }); - }); - group('pro token input', () { group('basic flow', () { final theApp = buildApp(onApply: () {}, isExpanded: true);