Merge branch 'master' into ux_fixes
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 748 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 861 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 153 KiB |
@@ -103,7 +103,7 @@ class GithubReleases {
|
||||
if (releases.isNotEmpty || canBeEmpty) {
|
||||
_releases = releases;
|
||||
} else {
|
||||
throw Exception("Github must contain at least 1 release.");
|
||||
throw Exception('Github must contain at least 1 release.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ class FlatpakMeta {
|
||||
final releases = List<Release>.empty(growable: true);
|
||||
if (addedTodaysVersion != null) {
|
||||
releases.add(Release(
|
||||
version: addedTodaysVersion, date: DateTime.now().toIso8601String().split("T").first));
|
||||
version: addedTodaysVersion, date: DateTime.now().toIso8601String().split('T').first));
|
||||
}
|
||||
if (fetchReleasesFromGithub) {
|
||||
if (_githubReleases == null) {
|
||||
|
||||
@@ -29,7 +29,8 @@ class WgerHttpException implements Exception {
|
||||
errors = {'unknown_error': 'An unknown error occurred, no further information available'};
|
||||
} else {
|
||||
try {
|
||||
errors = {'unknown_error': json.decode(responseBody)};
|
||||
final response = json.decode(responseBody);
|
||||
errors = (response is Map ? response : {'unknown_error': response}).cast<String, dynamic>();
|
||||
} catch (e) {
|
||||
errors = {'unknown_error': responseBody};
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ import 'package:wger/models/workouts/log.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
|
||||
void showErrorDialog(dynamic exception, BuildContext context) {
|
||||
log('showErrorDialog: ');
|
||||
log(exception.toString());
|
||||
log('=====================');
|
||||
// log('showErrorDialog: ');
|
||||
// log(exception.toString());
|
||||
// log('=====================');
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -55,6 +55,7 @@ void showHttpExceptionErrorDialog(WgerHttpException exception, BuildContext cont
|
||||
log('-------------------');
|
||||
|
||||
final List<Widget> errorList = [];
|
||||
|
||||
for (final key in exception.errors!.keys) {
|
||||
// Error headers
|
||||
// Ensure that the error heading first letter is capitalized.
|
||||
|
||||
@@ -401,7 +401,7 @@
|
||||
"@aboutBugsTitle": {
|
||||
"description": "Title for bugs section in the about dialog"
|
||||
},
|
||||
"aboutContactUsText": "Ako želi razgovarati s nama, skoči na Discord poslužitelj i kontaktiraj nas",
|
||||
"aboutContactUsText": "Ako želiš s nama razgovarati prijeđi na Discord poslužitelj i kontaktiraj nas",
|
||||
"@aboutContactUsText": {
|
||||
"description": "Text for contact us section in the about dialog"
|
||||
},
|
||||
@@ -825,5 +825,15 @@
|
||||
"description": "Message returned if no exercises match the searched string"
|
||||
},
|
||||
"aboutDonateTitle": "Doniraj",
|
||||
"@aboutDonateTitle": {}
|
||||
"@aboutDonateTitle": {},
|
||||
"aboutDonateText": "Pomogni projektu: kupi nam kavu, plati troškove poslužitelja i potiči nas u našem radu",
|
||||
"@aboutDonateText": {},
|
||||
"settingsTitle": "Postavke",
|
||||
"@settingsTitle": {},
|
||||
"settingsCacheTitle": "Predmemorija",
|
||||
"@settingsCacheTitle": {},
|
||||
"settingsCacheDescription": "Izvrši predmemoriju",
|
||||
"@settingsCacheDescription": {},
|
||||
"settingsCacheDeletedSnackbar": "Predmemorija je uspješno izbrisana",
|
||||
"@settingsCacheDeletedSnackbar": {}
|
||||
}
|
||||
|
||||
@@ -759,5 +759,21 @@
|
||||
"aboutMastodonText": "Projeyle ilgili güncellemeler ve haberler için bizi Mastodon'da takip edin",
|
||||
"@aboutMastodonText": {
|
||||
"description": "Text for the mastodon section in the about dialog"
|
||||
}
|
||||
},
|
||||
"settingsTitle": "Ayarlar",
|
||||
"@settingsTitle": {},
|
||||
"settingsCacheTitle": "Önbellek",
|
||||
"@settingsCacheTitle": {},
|
||||
"noMatchingExerciseFound": "Eşleşen egzersiz bulunamadı",
|
||||
"@noMatchingExerciseFound": {
|
||||
"description": "Message returned if no exercises match the searched string"
|
||||
},
|
||||
"aboutDonateTitle": "Bağış yap",
|
||||
"@aboutDonateTitle": {},
|
||||
"aboutDonateText": "Projeye yardımcı olmak, sunucu masraflarını karşılamak ve geliştirmeyi desteklemek için bağış yapın",
|
||||
"@aboutDonateText": {},
|
||||
"settingsCacheDescription": "Egzersiz önbelleği",
|
||||
"@settingsCacheDescription": {},
|
||||
"settingsCacheDeletedSnackbar": "Önbellek başarıyla temizlendi",
|
||||
"@settingsCacheDeletedSnackbar": {}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,7 @@ class AuthProvider with ChangeNotifier {
|
||||
/// Server application version
|
||||
Future<void> setServerVersion() async {
|
||||
final response = await client.get(makeUri(serverUrl!, SERVER_VERSION_URL));
|
||||
final responseData = json.decode(response.body);
|
||||
serverVersion = responseData;
|
||||
serverVersion = json.decode(response.body);
|
||||
}
|
||||
|
||||
Future<void> initData(String serverUrl) async {
|
||||
@@ -115,41 +114,39 @@ class AuthProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Registers a new user
|
||||
Future<Map<String, LoginActions>> register(
|
||||
{required String username,
|
||||
required String password,
|
||||
required String email,
|
||||
required String serverUrl}) async {
|
||||
Future<Map<String, LoginActions>> register({
|
||||
required String username,
|
||||
required String password,
|
||||
required String email,
|
||||
required String serverUrl,
|
||||
String locale = 'en',
|
||||
}) async {
|
||||
// Register
|
||||
try {
|
||||
final Map<String, String> data = {'username': username, 'password': password};
|
||||
if (email != '') {
|
||||
data['email'] = email;
|
||||
}
|
||||
final response = await client.post(
|
||||
makeUri(serverUrl, REGISTRATION_URL),
|
||||
headers: {
|
||||
HttpHeaders.contentTypeHeader: 'application/json; charset=UTF-8',
|
||||
HttpHeaders.authorizationHeader: 'Token ${metadata[MANIFEST_KEY_API]}',
|
||||
HttpHeaders.userAgentHeader: getAppNameHeader(),
|
||||
},
|
||||
body: json.encode(data),
|
||||
);
|
||||
final responseData = json.decode(response.body);
|
||||
|
||||
if (response.statusCode >= 400) {
|
||||
throw WgerHttpException(responseData);
|
||||
}
|
||||
|
||||
// If update is required don't log in user
|
||||
if (await applicationUpdateRequired()) {
|
||||
return {'action': LoginActions.update};
|
||||
}
|
||||
|
||||
return login(username, password, serverUrl);
|
||||
} catch (error) {
|
||||
rethrow;
|
||||
final Map<String, String> data = {'username': username, 'password': password};
|
||||
if (email != '') {
|
||||
data['email'] = email;
|
||||
}
|
||||
final response = await client.post(
|
||||
makeUri(serverUrl, REGISTRATION_URL),
|
||||
headers: {
|
||||
HttpHeaders.contentTypeHeader: 'application/json; charset=UTF-8',
|
||||
HttpHeaders.authorizationHeader: 'Token ${metadata[MANIFEST_KEY_API]}',
|
||||
HttpHeaders.userAgentHeader: getAppNameHeader(),
|
||||
HttpHeaders.acceptLanguageHeader: locale
|
||||
},
|
||||
body: json.encode(data),
|
||||
);
|
||||
|
||||
if (response.statusCode >= 400) {
|
||||
throw WgerHttpException(response.body);
|
||||
}
|
||||
|
||||
// If update is required don't log in user
|
||||
if (await applicationUpdateRequired()) {
|
||||
return {'action': LoginActions.update};
|
||||
}
|
||||
|
||||
return login(username, password, serverUrl);
|
||||
}
|
||||
|
||||
/// Authenticates a user
|
||||
@@ -160,48 +157,44 @@ class AuthProvider with ChangeNotifier {
|
||||
) async {
|
||||
await logout(shouldNotify: false);
|
||||
|
||||
try {
|
||||
final response = await client.post(
|
||||
makeUri(serverUrl, LOGIN_URL),
|
||||
headers: <String, String>{
|
||||
HttpHeaders.contentTypeHeader: 'application/json; charset=UTF-8',
|
||||
HttpHeaders.userAgentHeader: getAppNameHeader(),
|
||||
},
|
||||
body: json.encode({'username': username, 'password': password}),
|
||||
);
|
||||
final responseData = json.decode(response.body);
|
||||
final response = await client.post(
|
||||
makeUri(serverUrl, LOGIN_URL),
|
||||
headers: <String, String>{
|
||||
HttpHeaders.contentTypeHeader: 'application/json; charset=UTF-8',
|
||||
HttpHeaders.userAgentHeader: getAppNameHeader(),
|
||||
},
|
||||
body: json.encode({'username': username, 'password': password}),
|
||||
);
|
||||
final responseData = json.decode(response.body);
|
||||
|
||||
if (response.statusCode >= 400) {
|
||||
throw WgerHttpException(responseData);
|
||||
}
|
||||
|
||||
await initData(serverUrl);
|
||||
|
||||
// If update is required don't log in user
|
||||
if (await applicationUpdateRequired()) {
|
||||
return {'action': LoginActions.update};
|
||||
}
|
||||
|
||||
// Log user in
|
||||
token = responseData['token'];
|
||||
notifyListeners();
|
||||
|
||||
// store login data in shared preferences
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final userData = json.encode({
|
||||
'token': token,
|
||||
'serverUrl': this.serverUrl,
|
||||
});
|
||||
final serverData = json.encode({
|
||||
'serverUrl': this.serverUrl,
|
||||
});
|
||||
|
||||
prefs.setString('userData', userData);
|
||||
prefs.setString('lastServer', serverData);
|
||||
return {'action': LoginActions.proceed};
|
||||
} catch (error) {
|
||||
rethrow;
|
||||
if (response.statusCode >= 400) {
|
||||
throw WgerHttpException(response.body);
|
||||
}
|
||||
|
||||
await initData(serverUrl);
|
||||
|
||||
// If update is required don't log in user
|
||||
if (await applicationUpdateRequired()) {
|
||||
return {'action': LoginActions.update};
|
||||
}
|
||||
|
||||
// Log user in
|
||||
token = responseData['token'];
|
||||
notifyListeners();
|
||||
|
||||
// store login data in shared preferences
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final userData = json.encode({
|
||||
'token': token,
|
||||
'serverUrl': this.serverUrl,
|
||||
});
|
||||
final serverData = json.encode({
|
||||
'serverUrl': this.serverUrl,
|
||||
});
|
||||
|
||||
prefs.setString('userData', userData);
|
||||
prefs.setString('lastServer', serverData);
|
||||
return {'action': LoginActions.proceed};
|
||||
}
|
||||
|
||||
/// Loads the last server URL from which the user successfully logged in
|
||||
|
||||
@@ -37,7 +37,7 @@ class WgerBaseProvider {
|
||||
this.client = client ?? http.Client();
|
||||
}
|
||||
|
||||
Map<String, String> getDefaultHeaders({includeAuth = false}) {
|
||||
Map<String, String> getDefaultHeaders({bool includeAuth = false}) {
|
||||
final out = {
|
||||
HttpHeaders.contentTypeHeader: 'application/json; charset=UTF-8',
|
||||
HttpHeaders.userAgentHeader: auth.getAppNameHeader(),
|
||||
|
||||
@@ -177,16 +177,21 @@ class _AuthCardState extends State<AuthCard> {
|
||||
// Login existing user
|
||||
late Map<String, LoginActions> res;
|
||||
if (_authMode == AuthMode.Login) {
|
||||
res = await Provider.of<AuthProvider>(context, listen: false)
|
||||
.login(_authData['username']!, _authData['password']!, _authData['serverUrl']!);
|
||||
res = await Provider.of<AuthProvider>(context, listen: false).login(
|
||||
_authData['username']!,
|
||||
_authData['password']!,
|
||||
_authData['serverUrl']!,
|
||||
);
|
||||
|
||||
// Register new user
|
||||
} else {
|
||||
res = await Provider.of<AuthProvider>(context, listen: false).register(
|
||||
username: _authData['username']!,
|
||||
password: _authData['password']!,
|
||||
email: _authData['email']!,
|
||||
serverUrl: _authData['serverUrl']!);
|
||||
username: _authData['username']!,
|
||||
password: _authData['password']!,
|
||||
email: _authData['email']!,
|
||||
serverUrl: _authData['serverUrl']!,
|
||||
locale: Localizations.localeOf(context).languageCode,
|
||||
);
|
||||
}
|
||||
|
||||
// Check if update is required else continue normally
|
||||
|
||||
24
pubspec.lock
@@ -101,10 +101,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b"
|
||||
sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.7"
|
||||
version: "2.4.8"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -301,18 +301,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: drift
|
||||
sha256: "05363b695885c72036ed5c76287125bfc6f1deda20cb3aa044a09fe22792f81b"
|
||||
sha256: b50a8342c6ddf05be53bda1d246404cbad101b64dc73e8d6d1ac1090d119b4e2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.14.1"
|
||||
version: "2.15.0"
|
||||
drift_dev:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: drift_dev
|
||||
sha256: "50c14b8248d133d36b41c1b08ceed138be869b5b98ccaf3af16c9b88c7adc54e"
|
||||
sha256: c037d9431b6f8dc633652b1469e5f53aaec6e4eb405ed29dd232fa888ef10d88
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.14.1"
|
||||
version: "2.15.0"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -627,10 +627,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
|
||||
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "1.2.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1189,18 +1189,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqlite3_flutter_libs
|
||||
sha256: "3e3583b77cf888a68eae2e49ee4f025f66b86623ef0d83c297c8d903daa14871"
|
||||
sha256: "90963b515721d6a71e96f438175cf43c979493ed14822860a300b69694c74eb6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.18"
|
||||
version: "0.5.19+1"
|
||||
sqlparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqlparser
|
||||
sha256: "877fcefabb725d120e31f54fa669a98c002db0feeaca6cea5354543f03b5e906"
|
||||
sha256: dc384bb1f56d1384ce078edb5ff8247976abdab79d0c83e437210c85f06ecb61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.33.0"
|
||||
version: "0.34.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
10
pubspec.yaml
@@ -40,7 +40,7 @@ dependencies:
|
||||
flutter_html: ^3.0.0-beta.2
|
||||
flutter_typeahead: ^4.8.0
|
||||
font_awesome_flutter: ^10.4.0
|
||||
http: ^1.1.2
|
||||
http: ^1.2.0
|
||||
image_picker: ^1.0.6
|
||||
intl: ^0.18.1
|
||||
json_annotation: ^4.8.1
|
||||
@@ -59,10 +59,10 @@ dependencies:
|
||||
flutter_svg: ^2.0.5
|
||||
fl_chart: ^0.66.0
|
||||
flutter_zxing: ^1.5.2
|
||||
drift: ^2.13.1
|
||||
drift: ^2.15.0
|
||||
path: ^1.8.3
|
||||
path_provider: ^2.1.1
|
||||
sqlite3_flutter_libs: ^0.5.18
|
||||
sqlite3_flutter_libs: ^0.5.19+1
|
||||
get_it: ^7.6.4
|
||||
flex_seed_scheme: ^1.4.0
|
||||
flex_color_scheme: ^7.3.1
|
||||
@@ -73,13 +73,13 @@ dev_dependencies:
|
||||
sdk: flutter
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
build_runner: ^2.3.3
|
||||
build_runner: ^2.4.8
|
||||
json_serializable: ^6.7.1
|
||||
mockito: ^5.4.4
|
||||
network_image_mock: ^2.1.1
|
||||
flutter_lints: ^3.0.1
|
||||
cider: ^0.2.4
|
||||
drift_dev: ^2.13.1
|
||||
drift_dev: ^2.15.0
|
||||
freezed: ^2.4.5
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
|
||||
@@ -26,7 +26,6 @@ void main() {
|
||||
group('min application version check', () {
|
||||
test('app version higher than min version', () async {
|
||||
// arrange
|
||||
|
||||
when(mockClient.get(tVersionUri)).thenAnswer((_) => Future(() => Response('"1.2.0"', 200)));
|
||||
final updateNeeded = await authProvider.applicationUpdateRequired('1.3.0', testMetadata);
|
||||
|
||||
|
||||
@@ -16,87 +16,228 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/http.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/screens/auth_screen.dart';
|
||||
|
||||
import 'auth_screen_test.mocks.dart';
|
||||
|
||||
@GenerateMocks([http.Client])
|
||||
void main() {
|
||||
testWidgets('Test the widgets on the auth screen, login mode', (WidgetTester tester) async {
|
||||
// Wrap screen in material app so that the media query gets a context
|
||||
await tester.pumpWidget(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(
|
||||
create: (ctx) => AuthProvider(),
|
||||
),
|
||||
],
|
||||
child: Consumer<AuthProvider>(
|
||||
builder: (ctx, auth, _) => MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
locale: const Locale('en'),
|
||||
home: AuthScreen(),
|
||||
),
|
||||
late AuthProvider authProvider;
|
||||
late MockClient mockClient;
|
||||
|
||||
final Uri tRegistration = Uri(
|
||||
scheme: 'https',
|
||||
host: 'wger.de',
|
||||
path: 'api/v2/register/',
|
||||
);
|
||||
|
||||
final Uri tLogin = Uri(
|
||||
scheme: 'https',
|
||||
host: 'wger.de',
|
||||
path: 'api/v2/login/',
|
||||
);
|
||||
|
||||
final responseLoginOk = {'token': 'b01c44d3e3e016a615d2f82b16d31f8b924fb936'};
|
||||
|
||||
final responseRegistrationOk = {
|
||||
'message': 'api user successfully registered',
|
||||
'token': 'b01c44d3e3e016a615d2f82b16d31f8b924fb936'
|
||||
};
|
||||
|
||||
MultiProvider getWidget() {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (ctx) => authProvider),
|
||||
],
|
||||
child: Consumer<AuthProvider>(
|
||||
builder: (ctx, auth, _) => MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
locale: const Locale('en'),
|
||||
home: AuthScreen(),
|
||||
),
|
||||
),
|
||||
);
|
||||
/*
|
||||
Provider<Auth>(
|
||||
create: (_) => Auth(),
|
||||
// we use `builder` to obtain a new `BuildContext` that has access to the provider
|
||||
builder: (context) {
|
||||
// No longer throws
|
||||
return Text(''),
|
||||
}
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
mockClient = MockClient();
|
||||
authProvider = AuthProvider(mockClient, false);
|
||||
authProvider.serverUrl = 'https://wger.de';
|
||||
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
PackageInfo.setMockInitialValues(
|
||||
appName: 'wger',
|
||||
packageName: 'com.example.example',
|
||||
version: '1.2.3',
|
||||
buildNumber: '2',
|
||||
buildSignature: 'buildSignature',
|
||||
);
|
||||
|
||||
*/
|
||||
when(mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(responseLoginOk), 200)));
|
||||
|
||||
Consumer<AuthProvider>(
|
||||
builder: (ctx, auth, _) => MaterialApp(
|
||||
builder: (ctx, authResultSnapshot) => AuthScreen(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('WGER'), findsOneWidget);
|
||||
when(mockClient.get(
|
||||
any,
|
||||
)).thenAnswer((_) => Future(() => Response('"1.2.3.4"', 200)));
|
||||
|
||||
// Verify that the correct buttons and input fields are shown: login
|
||||
expect(find.text('Register now'), findsOneWidget);
|
||||
expect(find.text('LOGIN INSTEAD'), findsNothing);
|
||||
when(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(responseRegistrationOk), 201)));
|
||||
});
|
||||
|
||||
// Check that the correct widgets are shown
|
||||
expect(find.byKey(const Key('inputUsername')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputEmail')), findsNothing);
|
||||
expect(find.byKey(const Key('inputPassword')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputServer')), findsNothing);
|
||||
expect(find.byKey(const Key('inputPassword2')), findsNothing);
|
||||
expect(find.byKey(const Key('actionButton')), findsOneWidget);
|
||||
expect(find.byKey(const Key('toggleActionButton')), findsOneWidget);
|
||||
expect(find.byKey(const Key('toggleCustomServerButton')), findsOneWidget);
|
||||
}, skip: true); // TODO(x): skipped because of technical problems:
|
||||
// either the provider wasn't found or, if the call was removed, the
|
||||
// localization data could not be loaded...
|
||||
group('Login mode', () {
|
||||
testWidgets('Login smoke test', (WidgetTester tester) async {
|
||||
// Act
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
testWidgets('Test the widgets on the auth screen, registration', (WidgetTester tester) async {
|
||||
// Wrap screen in material app so that the media query gets a context
|
||||
await tester.pumpWidget(MaterialApp(home: AuthScreen()));
|
||||
await tester.tap(find.byKey(const Key('toggleActionButton')));
|
||||
// Assert
|
||||
expect(find.text('wger'), findsOneWidget);
|
||||
|
||||
// Rebuild the widget after the state has changed.
|
||||
await tester.pump();
|
||||
expect(find.text('Register now'), findsNothing);
|
||||
expect(find.text('LOGIN INSTEAD'), findsOneWidget);
|
||||
expect(find.textContaining("Don't have an account?"), findsOneWidget);
|
||||
expect(find.textContaining('Already have an account?'), findsNothing);
|
||||
|
||||
// Check that the correct widgets are shown
|
||||
expect(find.byKey(const Key('inputUsername')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputEmail')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputPassword')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputServer')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputPassword2')), findsOneWidget);
|
||||
expect(find.byKey(const Key('actionButton')), findsOneWidget);
|
||||
expect(find.byKey(const Key('toggleActionButton')), findsOneWidget);
|
||||
}, skip: true);
|
||||
expect(find.byKey(const Key('inputUsername')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputEmail')), findsNothing);
|
||||
expect(find.byKey(const Key('inputPassword')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputServer')), findsNothing);
|
||||
expect(find.byKey(const Key('inputPassword2')), findsNothing);
|
||||
expect(find.byKey(const Key('actionButton')), findsOneWidget);
|
||||
expect(find.byKey(const Key('toggleActionButton')), findsOneWidget);
|
||||
expect(find.byKey(const Key('toggleCustomServerButton')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Tests the login - happy path', (WidgetTester tester) async {
|
||||
// Arrange
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
// Act
|
||||
await tester.enterText(find.byKey(const Key('inputUsername')), 'testuser');
|
||||
await tester.enterText(find.byKey(const Key('inputPassword')), '123456789');
|
||||
await tester.tap(find.byKey(const Key('actionButton')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Assert
|
||||
expect(find.textContaining('An Error Occurred'), findsNothing);
|
||||
verify(mockClient.get(any));
|
||||
verify(mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
group('Registration mode', () {
|
||||
testWidgets('Registration smoke test', (WidgetTester tester) async {
|
||||
// Arrange
|
||||
await tester.binding.setSurfaceSize(const Size(1080, 1920));
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
// Act
|
||||
await tester.tap(find.byKey(const Key('toggleActionButton')));
|
||||
await tester.pump();
|
||||
|
||||
// Assert
|
||||
expect(find.textContaining("Don't have an account?"), findsNothing);
|
||||
expect(find.textContaining('Already have an account?'), findsOneWidget);
|
||||
|
||||
expect(find.byKey(const Key('inputUsername')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputEmail')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputPassword')), findsOneWidget);
|
||||
expect(find.byKey(const Key('inputServer')), findsNothing);
|
||||
expect(find.byKey(const Key('inputPassword2')), findsOneWidget);
|
||||
expect(find.byKey(const Key('actionButton')), findsOneWidget);
|
||||
expect(find.byKey(const Key('toggleActionButton')), findsOneWidget);
|
||||
|
||||
// Act - show custom server
|
||||
await tester.tap(find.byKey(const Key('toggleCustomServerButton')));
|
||||
await tester.pump();
|
||||
expect(find.byKey(const Key('inputServer')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Tests the registration - happy path', (WidgetTester tester) async {
|
||||
// Arrange
|
||||
await tester.binding.setSurfaceSize(const Size(1080, 1920));
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
// Act
|
||||
await tester.tap(find.byKey(const Key('toggleActionButton')));
|
||||
await tester.enterText(find.byKey(const Key('inputUsername')), 'testuser');
|
||||
await tester.enterText(find.byKey(const Key('inputPassword')), '123456789');
|
||||
await tester.enterText(find.byKey(const Key('inputPassword2')), '123456789');
|
||||
await tester.tap(find.byKey(const Key('actionButton')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Assert
|
||||
expect(find.textContaining('An Error Occurred'), findsNothing);
|
||||
verify(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
});
|
||||
|
||||
testWidgets('Tests the registration - password problems', (WidgetTester tester) async {
|
||||
// Arrange
|
||||
await tester.binding.setSurfaceSize(const Size(1080, 1920));
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
final response = {
|
||||
'username': [
|
||||
'This field must be unique.',
|
||||
],
|
||||
'password': [
|
||||
'This password is too common.',
|
||||
'This password is entirely numeric.',
|
||||
]
|
||||
};
|
||||
|
||||
when(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
// Act
|
||||
await tester.tap(find.byKey(const Key('toggleActionButton')));
|
||||
await tester.enterText(find.byKey(const Key('inputUsername')), 'testuser');
|
||||
await tester.enterText(find.byKey(const Key('inputPassword')), '123456789');
|
||||
await tester.enterText(find.byKey(const Key('inputPassword2')), '123456789');
|
||||
await tester.tap(find.byKey(const Key('actionButton')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Assert
|
||||
expect(find.textContaining('An Error Occurred'), findsOne);
|
||||
expect(find.textContaining('This password is too common'), findsOne);
|
||||
expect(find.textContaining('This password is entirely numeric'), findsOne);
|
||||
expect(find.textContaining('This field must be unique'), findsOne);
|
||||
|
||||
verify(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
279
test/auth/auth_screen_test.mocks.dart
Normal file
@@ -0,0 +1,279 @@
|
||||
// Mocks generated by Mockito 5.4.4 from annotations
|
||||
// in wger/test/auth/auth_screen_test.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i3;
|
||||
import 'dart:convert' as _i4;
|
||||
import 'dart:typed_data' as _i6;
|
||||
|
||||
import 'package:http/http.dart' as _i2;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:mockito/src/dummies.dart' as _i5;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: deprecated_member_use
|
||||
// ignore_for_file: deprecated_member_use_from_same_package
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: subtype_of_sealed_class
|
||||
|
||||
class _FakeResponse_0 extends _i1.SmartFake implements _i2.Response {
|
||||
_FakeResponse_0(
|
||||
Object parent,
|
||||
Invocation parentInvocation,
|
||||
) : super(
|
||||
parent,
|
||||
parentInvocation,
|
||||
);
|
||||
}
|
||||
|
||||
class _FakeStreamedResponse_1 extends _i1.SmartFake implements _i2.StreamedResponse {
|
||||
_FakeStreamedResponse_1(
|
||||
Object parent,
|
||||
Invocation parentInvocation,
|
||||
) : super(
|
||||
parent,
|
||||
parentInvocation,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [Client].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockClient extends _i1.Mock implements _i2.Client {
|
||||
MockClient() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.Response> head(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#head,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#head,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.Response>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.Response> get(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#get,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#get,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.Response>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.Response> post(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
Object? body,
|
||||
_i4.Encoding? encoding,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#post,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#post,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.Response>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.Response> put(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
Object? body,
|
||||
_i4.Encoding? encoding,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#put,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#put,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.Response>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.Response> patch(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
Object? body,
|
||||
_i4.Encoding? encoding,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#patch,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#patch,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.Response>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.Response> delete(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
Object? body,
|
||||
_i4.Encoding? encoding,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#delete,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#delete,
|
||||
[url],
|
||||
{
|
||||
#headers: headers,
|
||||
#body: body,
|
||||
#encoding: encoding,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.Response>);
|
||||
|
||||
@override
|
||||
_i3.Future<String> read(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#read,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
returnValue: _i3.Future<String>.value(_i5.dummyValue<String>(
|
||||
this,
|
||||
Invocation.method(
|
||||
#read,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<String>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i6.Uint8List> readBytes(
|
||||
Uri? url, {
|
||||
Map<String, String>? headers,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#readBytes,
|
||||
[url],
|
||||
{#headers: headers},
|
||||
),
|
||||
returnValue: _i3.Future<_i6.Uint8List>.value(_i6.Uint8List(0)),
|
||||
) as _i3.Future<_i6.Uint8List>);
|
||||
|
||||
@override
|
||||
_i3.Future<_i2.StreamedResponse> send(_i2.BaseRequest? request) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#send,
|
||||
[request],
|
||||
),
|
||||
returnValue: _i3.Future<_i2.StreamedResponse>.value(_FakeStreamedResponse_1(
|
||||
this,
|
||||
Invocation.method(
|
||||
#send,
|
||||
[request],
|
||||
),
|
||||
)),
|
||||
) as _i3.Future<_i2.StreamedResponse>);
|
||||
|
||||
@override
|
||||
void close() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#close,
|
||||
[],
|
||||
),
|
||||
returnValueForMissingStub: null,
|
||||
);
|
||||
}
|
||||
@@ -40,8 +40,8 @@ void main() {
|
||||
expect(exercise.uuid, '1b020b3a-3732-4c7e-92fd-a0cec90ed69b');
|
||||
expect(exercise.categoryId, 10);
|
||||
expect(exercise.variationId, 25);
|
||||
expect(exercise.authors, ["Foo Bar"]);
|
||||
expect(exercise.authorsGlobal, ["Foo Bar", "tester McTestface", "Mr. X"]);
|
||||
expect(exercise.authors, ['Foo Bar']);
|
||||
expect(exercise.authorsGlobal, ['Foo Bar', 'tester McTestface', 'Mr. X']);
|
||||
expect(exercise.equipment.map((e) => e.name), ['Kettlebell']);
|
||||
expect(exercise.muscles.map((e) => e.name), [
|
||||
'Biceps femoris',
|
||||
|
||||
@@ -195,7 +195,7 @@ class MockGalleryProvider extends _i1.Mock implements _i4.GalleryProvider {
|
||||
) as _i6.Future<void>);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -195,7 +195,7 @@ class MockGalleryProvider extends _i1.Mock implements _i4.GalleryProvider {
|
||||
) as _i6.Future<void>);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -108,7 +108,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -123,7 +123,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
@@ -395,6 +395,7 @@ class MockAuthProvider extends _i1.Mock implements _i2.AuthProvider {
|
||||
required String? password,
|
||||
required String? email,
|
||||
required String? serverUrl,
|
||||
String? locale = r'en',
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -405,6 +406,7 @@ class MockAuthProvider extends _i1.Mock implements _i2.AuthProvider {
|
||||
#password: password,
|
||||
#email: email,
|
||||
#serverUrl: serverUrl,
|
||||
#locale: locale,
|
||||
},
|
||||
),
|
||||
returnValue: _i5.Future<Map<String, _i2.LoginActions>>.value(<String, _i2.LoginActions>{}),
|
||||
|
||||
@@ -234,6 +234,7 @@ class MockAuthProvider extends _i1.Mock implements _i3.AuthProvider {
|
||||
required String? password,
|
||||
required String? email,
|
||||
required String? serverUrl,
|
||||
String? locale = r'en',
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -244,6 +245,7 @@ class MockAuthProvider extends _i1.Mock implements _i3.AuthProvider {
|
||||
#password: password,
|
||||
#email: email,
|
||||
#serverUrl: serverUrl,
|
||||
#locale: locale,
|
||||
},
|
||||
),
|
||||
returnValue: _i5.Future<Map<String, _i3.LoginActions>>.value(<String, _i3.LoginActions>{}),
|
||||
@@ -399,7 +401,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i8.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -108,7 +108,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -108,7 +108,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -186,7 +186,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -108,7 +108,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -108,7 +108,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -108,7 +108,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i4.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -755,7 +755,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i2.WgerBaseProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
Map<String, String> getDefaultHeaders({dynamic includeAuth = false}) => (super.noSuchMethod(
|
||||
Map<String, String> getDefaultHeaders({bool? includeAuth = false}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getDefaultHeaders,
|
||||
[],
|
||||
|
||||
@@ -211,7 +211,8 @@ final benchPressDE = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Bankdrücken LH',
|
||||
description:
|
||||
'''<p>Lege dich auf die Bank, die Stange direkt über die Augen, die Knie etwas angewinkelt und die Füße fest auf dem Boden. Greife die Stange breit und lasse sie langsam und kontrolliert runter, dabei sollte die Stange kurz auf Brustwarzenhöhe den Körper berühren. Dann das Gewicht wieder hochdrücken bis die Arme durchgestreckt sind.</p>
|
||||
'''
|
||||
<p>Lege dich auf die Bank, die Stange direkt über die Augen, die Knie etwas angewinkelt und die Füße fest auf dem Boden. Greife die Stange breit und lasse sie langsam und kontrolliert runter, dabei sollte die Stange kurz auf Brustwarzenhöhe den Körper berühren. Dann das Gewicht wieder hochdrücken bis die Arme durchgestreckt sind.</p>
|
||||
<p>Bei hohem Gewicht, empfielt sich natürlich einen <em>Spotter</em> zu haben, der einen hilft falls man die Stange nicht alleine hochdrücken kann.</p>
|
||||
<p>Mit der Breite des Griffs kann außerdem kontrolliert werden, welcher Bereich der Brust stärker belastet wird:</p>
|
||||
<ul>
|
||||
@@ -228,7 +229,8 @@ final benchPressEN = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Bench Press',
|
||||
description:
|
||||
'''<p>Lay down on a bench, the bar should be directly above your eyes, the knees are somewhat angled and the feet are firmly on the floor. Concentrate, breath deeply and grab the bar more than shoulder wide. Bring it slowly down till it briefly touches your chest at the height of your nipples. Push the bar up.</p>
|
||||
'''
|
||||
<p>Lay down on a bench, the bar should be directly above your eyes, the knees are somewhat angled and the feet are firmly on the floor. Concentrate, breath deeply and grab the bar more than shoulder wide. Bring it slowly down till it briefly touches your chest at the height of your nipples. Push the bar up.</p>
|
||||
<p>If you train with a high weight it is advisable to have a <em>spotter</em> that can help you up if you can't lift the weight on your own.</p>
|
||||
<p>With the width of the grip you can also control which part of the chest is trained more:</p>
|
||||
<ul>
|
||||
@@ -257,7 +259,8 @@ final deadLiftEN = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Deadlifts',
|
||||
description:
|
||||
'''<p>Stand firmly, with your feet slightly more than shoulder wide apart. Stand directly behind the bar where it should barely touch your shin, your feet pointing a bit out. Bend down with a straight back, the knees also pointing somewhat out. Grab the bar with a shoulder wide grip, one underhand, one reverse grip.</p>
|
||||
'''
|
||||
<p>Stand firmly, with your feet slightly more than shoulder wide apart. Stand directly behind the bar where it should barely touch your shin, your feet pointing a bit out. Bend down with a straight back, the knees also pointing somewhat out. Grab the bar with a shoulder wide grip, one underhand, one reverse grip.</p>
|
||||
<p>Pull the weight up. At the highest point make a slight hollow back and pull the bar back. Hold 1 or 2 seconds that position. Go down, making sure the back is not bent. Once down you can either go back again as soon as the weights touch the floor, or make a pause, depending on the weight.</p>''',
|
||||
exerciseId: 184,
|
||||
language: tLanguage2,
|
||||
@@ -269,7 +272,8 @@ final deadLiftDE = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Kreuzheben',
|
||||
description:
|
||||
'''<p>Stelle dich mit etwas mehr als schulterbreitem Stand vor der Stange, die Füße zeigen leicht nach außen, die Stange ist direkt darüber und sehr nahe am Schienbein. Beuge die Knie (zeigen ebenfalls etwas nach außen) und neige den Oberkörper (bleibt während der ganzen Übung gerade). Greife die Stange schulterbreit mit einem Unter- und einem Obergriff.</p>
|
||||
'''
|
||||
<p>Stelle dich mit etwas mehr als schulterbreitem Stand vor der Stange, die Füße zeigen leicht nach außen, die Stange ist direkt darüber und sehr nahe am Schienbein. Beuge die Knie (zeigen ebenfalls etwas nach außen) und neige den Oberkörper (bleibt während der ganzen Übung gerade). Greife die Stange schulterbreit mit einem Unter- und einem Obergriff.</p>
|
||||
<p>Ziehe nun die Stange nach oben. An der höchsten Stelle mache ein leichtes Hohlkreuz und drücke die Schultern nach hinten. Gehe wieder runter, wobei du darauf achtest, dass der Rücken gerade bleibt und sich nicht krümmt. Du kannst unten angekommen eine kleine Pause einlegen oder sofort weitermachen.</p>''',
|
||||
exerciseId: 184,
|
||||
language: tLanguage1,
|
||||
@@ -281,7 +285,8 @@ final deadLiftPT = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Levantamento terra',
|
||||
description:
|
||||
'''Fique firme, com os pés ligeiramente mais afastados do que os ombros. Fique diretamente atrás da barra, onde ela mal deve tocar sua canela, com os pés apontando um pouco para fora. Curve-se com as costas retas, os joelhos também apontando um pouco para fora. Agarre a barra com uma pegada na largura dos ombros, uma pegada por baixo e uma pegada reversa.
|
||||
'''
|
||||
Fique firme, com os pés ligeiramente mais afastados do que os ombros. Fique diretamente atrás da barra, onde ela mal deve tocar sua canela, com os pés apontando um pouco para fora. Curve-se com as costas retas, os joelhos também apontando um pouco para fora. Agarre a barra com uma pegada na largura dos ombros, uma pegada por baixo e uma pegada reversa.
|
||||
|
||||
Puxe o peso para cima. No ponto mais alto, faça uma leve depressão para trás e puxe a barra para trás. Segure 1 ou 2 segundos nessa posição. Desça, certificando-se de que as costas não estão dobradas. Depois de descer, você pode voltar assim que os pesos tocarem o chão ou fazer uma pausa, dependendo do peso.''',
|
||||
exerciseId: 184,
|
||||
@@ -293,7 +298,8 @@ final deadLiftIT = Translation(
|
||||
uuid: '7c088d54-6732-4d5e-aae8-9be8d4a1f111',
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Stacco',
|
||||
description: '''StaccoStacco
|
||||
description: '''
|
||||
StaccoStacco
|
||||
Stacco''',
|
||||
exerciseId: 184,
|
||||
language: tLanguage13,
|
||||
@@ -373,7 +379,8 @@ final crunchesDE = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Crunches',
|
||||
description:
|
||||
'''<p>Lege dich auf eine Matte mit angewinkelten Beinen. Die Füße werden irgendwie festgehalten (Partner, Lanhghantel, o.Ä.) und die Hände werden hinter dem Nacken verschränkt. Aus dieser Position führe den Oberkörper so weit nach oben, bis Kopf oder Ellenbogen die angewinkelten Beine berühren.</p>
|
||||
'''
|
||||
<p>Lege dich auf eine Matte mit angewinkelten Beinen. Die Füße werden irgendwie festgehalten (Partner, Lanhghantel, o.Ä.) und die Hände werden hinter dem Nacken verschränkt. Aus dieser Position führe den Oberkörper so weit nach oben, bis Kopf oder Ellenbogen die angewinkelten Beine berühren.</p>
|
||||
<p>Es ist wichtig, dass dieser Vorgang mit einer rollenden Bewegung durchgeführt wird: die Wirbelsäule sollte sich Wirbel für Wirbel von der Matte lösen. Ein Hohlkreuz ist stets zu vermeiden.</p>''',
|
||||
exerciseId: 167,
|
||||
language: tLanguage1,
|
||||
@@ -500,7 +507,8 @@ final curlsEN = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Biceps Curls With Dumbbell',
|
||||
description:
|
||||
'''<p>Hold two barbells, the arms are streched, the hands are on your side, the palms face inwards. Bend the arms and bring the weight with a fast movement up. At the same time, rotate your arms by 90 degrees at the very beginning of the movement. At the highest point, rotate a little the weights further outwards. Without a pause, bring them down, slowly.</p>
|
||||
'''
|
||||
<p>Hold two barbells, the arms are streched, the hands are on your side, the palms face inwards. Bend the arms and bring the weight with a fast movement up. At the same time, rotate your arms by 90 degrees at the very beginning of the movement. At the highest point, rotate a little the weights further outwards. Without a pause, bring them down, slowly.</p>
|
||||
<p>Don't allow your body to swing during the exercise, all work is done by the biceps, which are the only mucles that should move (pay attention to the elbows).</p>''',
|
||||
exerciseId: 92,
|
||||
language: tLanguage2,
|
||||
@@ -512,7 +520,8 @@ final curlsDE = Translation(
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Bizeps KH-Curls',
|
||||
description:
|
||||
'''<p>Halte zwei Kurzhantel mit ausgestreckten Armen neben dem Körper, die Handflächen zeigen nach innen. Beuge die Arme und brige die Hanteln mit einer schnellen Bewegung nach oben wobei sie gleichzeitig um 90 Grad gedreht werden. Am höchsten Punkt kann man die Hanteln ganz leicht weiter nach außen drehen. Ohne Pause wird das Gewicht nun kontrolliert nach unten gebracht. Beachte, dass die Bewegung nach oben schneller ist als nach unten.</p>
|
||||
'''
|
||||
<p>Halte zwei Kurzhantel mit ausgestreckten Armen neben dem Körper, die Handflächen zeigen nach innen. Beuge die Arme und brige die Hanteln mit einer schnellen Bewegung nach oben wobei sie gleichzeitig um 90 Grad gedreht werden. Am höchsten Punkt kann man die Hanteln ganz leicht weiter nach außen drehen. Ohne Pause wird das Gewicht nun kontrolliert nach unten gebracht. Beachte, dass die Bewegung nach oben schneller ist als nach unten.</p>
|
||||
<p>Während des Bewegungablaufs darf der Körper nicht mitschwingen. Die Ellenbogen bleiben dabei immer an der Stelle.</p>''',
|
||||
exerciseId: 92,
|
||||
language: tLanguage1,
|
||||
@@ -557,7 +566,8 @@ final raisesDE = Translation(
|
||||
uuid: '72e78f4d-65f7-4ddd-9247-cdc1e133fa80',
|
||||
created: DateTime(2021, 1, 15),
|
||||
name: 'Seitheben KH',
|
||||
description: '''<ol>
|
||||
description: '''
|
||||
<ol>
|
||||
<li>Aufrechter Stand, Kopf nach vorne gerichtet, eine Kurzhantel in jeder Hand.</li>
|
||||
<li>Handflächen nach innen, in Richtung des Körpers, gerichtet.</li>
|
||||
<li>Hebe die Hanteln seitlich nach oben, ohne Schwung zu holen. Atme aus. Die Ellenbogen sind leicht gebeugt. Hebe die Kurzhanteln soweit, bis die Arme parallel zum Boden sind.</li>
|
||||
|
||||