Skip to content

Commit

Permalink
Merge pull request #239 from lyskouski/RF-228
Browse files Browse the repository at this point in the history
[#228] [RF] Improve Cove Coverage
  • Loading branch information
lyskouski authored Sep 8, 2023
2 parents 4124ccd + 10357c6 commit f45c778
Show file tree
Hide file tree
Showing 22 changed files with 292 additions and 138 deletions.
55 changes: 18 additions & 37 deletions docs/implementation-flow/ch-intro.tex
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,34 @@
In today's fast-paced digital world, businesses strive to adopt innovative technologies to streamline their
operations and deliver exceptional user experiences. Mobile applications have become indispensable tools
for organizations seeking to engage with their customers, increase efficiency, and stay ahead of the competition.
Flutter, a powerful open-source UI framework developed by Google, has emerged as a popular choice for building
high-performance, cross-platform mobile applications.
Flutter has emerged as a popular choice for building
high-performance, platform-agnostic applications.

This book, "Flutter Serverless Applications Development: A Financial Accounting Application Development Guide"
takes you on a comprehensive journey through the creation of a robust financial accounting application using
Flutter and serverless architecture. By combining the flexibility of Flutter with the scalability and
cost-effectiveness of serverless computing, you'll learn how to build powerful and efficient mobile applications.
This book, "From Nothing to Market with Flutter: Desktop, Mobile, and Web Distribution" takes us to a comprehensive
journey through the creation of a robust competitive application by using Flutter with no-server architecture (while
\q{serverless} is mostly associated with cloud-based infrastructure). And go through building a powerful and efficient
application together.

The primary focus of this book is to demonstrate how to leverage Flutter's rich ecosystem and serverless approach,
to create a feature-rich financial accounting application. Throughout the chapters, you'll explore the various
The primary focus of this book is to demonstrate how to leverage Flutter's rich ecosystem and no-server approach,
to create a feature-rich (financial accounting) application. Throughout the chapters, you'll explore the various
stages of application development, from conceptualization to deployment, while adhering to best practices and
design patterns.
\\
\noindent Key features of this book:
\begin{itemize}
\item Introduction to Flutter: Begin by understanding the basics of Flutter, its architecture, and how it
enables cross-platform development. Learn about the Flutter SDK, widgets, and the Dart programming language,
which forms the foundation of Flutter applications.
\item Understand Flutter architecture, and how it enables cross-platform development. Make an overview of
the Dart programming language, which forms the foundation of Flutter applications.

\item Serverless Computing: Explore the advantages of serverless architecture and its role in building
scalable and cost-effective applications.

\item Designing the Financial Accounting Application: Gain insights into the design principles of a financial
accounting application.
\item Gain insights into the design principles of an application development and distribution.

\item UI/UX: Learn how to create an intuitive user interface.

\item Implementing Core Functionality: Discover how to incorporate essential features into your application,
such as managing financial transactions, generating reports, and performing calculations. Understand how
serverless functions can be leveraged to handle complex business logic efficiently.

\item Integrating External Services: Learn how to integrate third-party services, such as payment gateways
and financial APIs, into your application. Explore strategies for securely interacting with external
systems and ensuring data integrity.
\item Go through User Interface and Experience practices to create an intuitive user interface.

\item Testing and Debugging: Master techniques for testing your Flutter application, including unit testing,
widget testing, and integration testing. Gain insights into effective debugging practices to identify and
resolve issues efficiently.
\item Discover how to incorporate essential features into the application with a forecast release planning.

\item Deployment and Maintenance: Learn how to prepare your application for deployment across multiple
platforms, including iOS and Android. Understand the best practices for app store submission and explore
strategies for ongoing maintenance and updates.
\end{itemize}
\item Explore strategies for securely interacting with external systems and ensuring data integrity.

Throughout the book, you'll follow a hands-on approach, implementing real-world examples and practical exercises.
By the end, you'll have the skills and knowledge to build a powerful application using Flutter, equipped to
handle complex operations while delivering a seamless user experience.
\item Master techniques for testing (unit, widget, integration, and performance tests) and debugging practices.

Embark on this exciting journey of Flutter serverless application development, and unlock the potential of
building scalable and efficient applications that meet the demands of modern businesses.
\item Configure the application distribution across all platforms, and explore strategies for ongoing
maintenance and updates.
\end{itemize}
Empty file.
46 changes: 46 additions & 0 deletions docs/implementation-flow/ch01-s01-dart.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
% Copyright 2023 The terCAD team. All rights reserved.
% Use of this content is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.

\subsection{Dart}
\markboth{Bootcamping}{Dart}

\subsubsection{Overloading operators}

In Dart, "magic methods" are often referred to as "operator overloading" or "special methods." They allow you to define
custom behaviors for built-in operations:

\begin{itemize}
\item \q{toString} returns a string representation of an object, can be used for a serialization and deserialization
process of an object;
\item \q{call} allows an object to be treated as a function;
\item \q{hashCode} returns a hash code for an object (to use object as a key for \q{Map} and \q{Set});
\item \q{operator==} compares two objects for equality;
\item \q{get} and \q{set} -- to override the behavior of getting and setting properties.
\end{itemize}

\begin{lstlisting}
class Person {
// Required from constructor
String name;
// Post-initialization
late DateTime _createdAt = DateTime.now();
// var person = Person('Tom');
Person(this.name);
// person() // 'Hello from Tom!'
String call() => 'Hello from $name!';
// person.createdAt = DateTime(2023, 01, 01);
set createdAt(DateTime date) => _createdAt = date;
// print(person.createdAt); // 2023-01-01 00:00:00
DateTime get createdAt => _createdAt;
// print(Person('Tom') == Person('Terry')); // false
@override
bool operator ==(Person other) => other.name == name;
// person = Person.fromString('Tom');
factory Person.fromString(String name) {
return Person(name);
}
// print(person); // 'Tom'
@override
String toString() => name;
}
\end{lstlisting}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
\subsection{[TBD] Dart}

Question: Flutter check that variable is a function

Answer: In Flutter, you can use the is operator to check if a variable is a function.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
% Copyright 2023 The terCAD team. All rights reserved.
% Use of this content is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.

\markboth{Bootcamping Flutter}{Bootcamping Flutter}

[TBD]
\subsection{Flutter}
\markboth{Bootcamping}{Flutter}


\subsubsection{Asserting Functions Definition}
Expand Down Expand Up @@ -39,59 +38,6 @@ \subsubsection{Ignoring Function Arguments}
\end{lstlisting}


\subsubsection{Applying Getters and Setters for Class Variables}

By migrating our data structures to class objects it can be used additionally getter and setter for class variables.
That will help us to cover, as an example, \q{description}-attribute for Budget structures by showing
"Spent Amount / Total Budget", and for \q{details}-attribute - "Left Amount".

\begin{lstlisting}
class MyClass {
String _name; // Private variable

// Getter for name
String get name => _name;

// Setter for name
set name(String value) {
_name = value;
}
}

void main() {
MyClass myObject = MyClass();

// Using the setter
myObject.name = 'John';

// Using the getter
print(myObject.name); // Output: John
}
\end{lstlisting}

In the example above, the \q{MyClass}-class has a private variable \q{\_name}. The getter for \q{\_name} is defined
using the get keyword, and the setter is defined using the set keyword. The getter returns the value of
\q{\_name}, and the setter sets the value of \q{\_name} to the provided value. By using that approach we can control
the access to class variables and perform additional logic or validation when getting or setting their values.

One more question, is how to set \q{DateTime.now()} inside a constructor as default value, since, by defining it inside
the constructor, an error would be taken: The default value of an optional parameter must be constant.

So, to set a default value for a DateTime variable as the current date and time, we can use the \q{DateTime.now()} method
during the initialization of the variable.

\begin{lstlisting}
class MyClass {
DateTime _createdAt;

MyClass({DateTime? createdAt})
: _createdAt = createdAt ?? DateTime.now();

DateTime get createdAt => _createdAt;
}
\end{lstlisting}


\subsubsection{Using cast to resolve dynamic structures}

Migration our Bills to classes construction has lead to an error on .firstWhere when Account of Budget not found.
Expand Down
File renamed without changes.
6 changes: 0 additions & 6 deletions docs/implementation-flow/ch01-serverless.tex

This file was deleted.

16 changes: 6 additions & 10 deletions docs/implementation-flow/index.tex
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
\fancyhead[RO]{\thepage}

\author{Viachaslau Lyskouski}
\title{Flutter for Serverless Applications}
%\subtitle{From Nothing to Market}
\title{From Nothing to Market with Flutter}
%\subtitle{Desktop, Mobile, and Web Distribution}
\date{2023}

\begin{document}
Expand Down Expand Up @@ -93,14 +93,10 @@ \section*{Introduction}

\newpage
\section{[TBD] Bootcamping}
\input{./ch00-s01-dart}
\input{./ch00-s01-dart.tex-dump}
\input{./ch00-s02-flutter}
\input{./ch00-s02-flutter.tex-dump}

\newpage
\section{[TBD] Observing Serverless Computing}
\input{./ch01-serverless}
\input{./ch01-s01-dart}
\input{./ch01-s01-dart.tex-dump}
\input{./ch01-s02-flutter}
\input{./ch01-s02-flutter.tex-dump}

\newpage
\section{[TBD] Conceptualizing Design}
Expand Down
2 changes: 1 addition & 1 deletion docs/implementation-flow/references.tex
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
\bibitem[Rich20]{Rich20} Mark Richards, Neal Ford, ``Fundamentals of Software Architecture",
\emph{O'Reilly Media}, ISBN 9781492043454, March 2020

\bibitem[Kass05]{Kass05} Ioannis T. Kassios, ``Decoupling in Object Orientation", \emph{Formal Methods. FM 2005.
\bibitem[Kass05]{Kass05} Ioannis T. Kassios, ``Decoupling in Object Orientation", \emph{Formal Methods. FM 2005.
Lecture Notes in Computer Science, vol 3582. Springer, Berlin, Heidelberg}, DOI 10.1007/11526841\_5, 2005

\end{thebibliography}
4 changes: 4 additions & 0 deletions lib/_classes/controller/focus_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class FocusController {
}

static ScrollController getController(Type name) {
if (_controller[name] != null && _controller[name]!.hasClients) {
_controller[name]!.dispose();
_controller[name] = null;
}
_controller[name] ??= ScrollController();
_activeClass = name;
return _controller[name]!;
Expand Down
26 changes: 11 additions & 15 deletions lib/_classes/herald/app_locale.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ class AppLocale extends ValueNotifier<Locale?> with SharedPreferencesMixin {
AppLocale([Locale? value]) : super(value) {
final newValue = getPreference(prefLocale);
if (newValue != null) {
final loc = fromCode(newValue);
if (loc != null && AppLocalizations.supportedLocales.contains(loc)) {
_set(loc);
}
set(newValue);
}
}

Expand All @@ -27,22 +24,21 @@ class AppLocale extends ValueNotifier<Locale?> with SharedPreferencesMixin {
}
}

void _set(Locale newValue) {
if (newValue != value) {
value = newValue;
void set(String newValue, [Function? callback]) {
final loc = fromCode(newValue);
if (loc != null && loc != value && AppLocalizations.supportedLocales.contains(loc)) {
value = loc;
code = value.toString();
if (callback != null) {
callback();
}
notifyListeners();
}
}

updateState(BuildContext context) {
void updateState(BuildContext context) {
final value = Localizations.localeOf(context).toString();
final loc = fromCode(value);
if (loc != null) {
labels = AppLocalizations.of(context)!;
setPreference(prefLocale, value).then((_) {
_set(loc);
});
}
labels = AppLocalizations.of(context)!;
set(value, () => setPreference(prefLocale, value));
}
}
9 changes: 4 additions & 5 deletions lib/_classes/herald/app_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class AppTheme extends ValueNotifier<ThemeMode> with SharedPreferencesMixin {

_set(String val) {
int? idx = int.tryParse(val);
if (idx != null) {
if (idx != null && idx < ThemeMode.values.length) {
final newValue = ThemeMode.values[idx];
if (newValue != value) {
value = newValue;
Expand All @@ -23,9 +23,8 @@ class AppTheme extends ValueNotifier<ThemeMode> with SharedPreferencesMixin {
}
}

updateState(String value) {
setPreference(prefTheme, value).then((_) {
_set(value);
});
Future<void> setTheme(String value) async {
await setPreference(prefTheme, value);
_set(value);
}
}
2 changes: 1 addition & 1 deletion lib/widgets/automation/sync_tab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class SyncTabState extends State<SyncTab> {

void synchronize() {
setState(() => loading = true);
dataProvider.getList(AppDataType.accounts).forEach((o) => sync.send(o.toStream()));
dataProvider.getList(AppDataType.budgets).forEach((o) => sync.send(o.toStream()));
dataProvider.getActualList(AppDataType.bills).forEach((o) => sync.send(o.toStream()));
dataProvider.getList(AppDataType.accounts).forEach((o) => sync.send(o.toStream()));
setState(() => loading = false);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(AppLocale.labels.peerSent)),
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/start/setting_tab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class SettingTabState<T extends SettingTab> extends AbstractTabState<T> with Sha

void saveTheme(String value) {
setState(() => brightness = value);
theme.updateState(value);
theme.setTheme(value);
}

Future<void> initCurrencyFromLocale(String locale) async {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/account/create_and_view_accounts.feature
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ Feature: Verify Account Functionality
| Credit Card | 1500 | JPY | ¥1,500 |
| Debit Card | 500.256 | GBP | £500.26 |
| Deposit | 10000 | AUD | $10,000.00 |
# | Credit | 1000000 | CNY | ¥1,000,000.00 |
| Credit | 1000000 | CNY | ¥1,000,000.00 |
6 changes: 1 addition & 5 deletions test/e2e/account/create_and_view_accounts.resource
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
@account @currency
@account
Feature: Verify Account functionality alignment with expectations

Scenario: Opened Account Form
Given I am on "Accounts" page
When I tap "Add Account" button
Then I can see "Create new Account" component

Scenario: Opened Budget Form
Given I am on "Budgets" page
When I tap "Add new Budget Category" button
Then I can see "Create new Budget Category" component
22 changes: 22 additions & 0 deletions test/e2e/budget/create_and_view_budget.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@budget @currency
Feature: Verify Budget Functionality

Scenario Outline: Created different Budget types
Given Opened Budget Form
When I enter "<name>" to "Enter Budget Category Name" text field
And I enter "<amount>" to "Set Balance" text field
And I tap on 0 index of "CurrencySelector" fields
And I enter "<currency>" to "Type Code" text field
And I tap on 1 index of "<currency>" element
And I tap "Close" element # Popup with icons
And I tap "Create new Budget Category" button
Then I can see "Budgets, left" component
And I can see "<name_result>" component
And I can see "<result>" component

Examples:
| name | amount | currency | result | name_result |
| Limited | 100 | EUR | €100.00 left | Limited |
| Unlimited | 0 | USD | $0.00 spent | Unlimited |
| Group / 1 | 50 | USD | $50.00 left | Group / 1 |
| Group / 2 | 75 | USD | €0.00 / €125.00 | Group |
8 changes: 8 additions & 0 deletions test/e2e/budget/create_and_view_budget.resource
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

@budget
Feature: Verify Budget functionality alignment with expectations

Scenario: Opened Budget Form
Given I am on "Budgets" page
When I tap "Add new Budget Category" button
Then I can see "Create new Budget Category" component
Loading

0 comments on commit f45c778

Please sign in to comment.