Skip to content

Commit fdf9d26

Browse files
committed
setting up integration tests on CI
1 parent d555da2 commit fdf9d26

17 files changed

Lines changed: 112 additions & 78 deletions

File tree

integration_test/category/category_manager_integration_test.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'dart:convert';
22

33
import 'package:chrono_sheet/category/model/icon_info.dart';
4-
import 'package:chrono_sheet/category/service/category_manager.dart';
4+
import 'package:chrono_sheet/category/service/shared_category_data_manager.dart';
55
import 'package:chrono_sheet/google/drive/service/google_drive_service.dart';
66
import 'package:chrono_sheet/main.dart' as app;
77
import 'package:chrono_sheet/sheet/model/sheet_model.dart';
@@ -36,8 +36,7 @@ void main() {
3636
await gService.getOrCreateFile(remoteDirId, testContext.testId, sheetMimeType, true);
3737
}
3838

39-
// TODO name accordingly
40-
testWidgets("integration-test", (WidgetTester tester) async {
39+
testWidgets("saving category icons in remote storage", (WidgetTester tester) async {
4140
final main = MainScreenDriver(tester);
4241
final chooseSheet = ChooseSheetScreenDriver(tester);
4342
final manageCategory = ManageCategoryScreenDriver(tester);
@@ -48,7 +47,7 @@ void main() {
4847
app.main();
4948
await tester.pumpAndSettle();
5049

51-
await main.clickSelectFile();
50+
await main.clickSelectGoogleFile();
5251
await chooseSheet.selectTestSheet();
5352

5453
await main.clickAddCategory();

integration_test/framework/driver/category/manage/category_manage_screen_driver.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import 'dart:io';
22

33
import 'package:chrono_sheet/category/service/category_icon_selector.dart';
4+
import 'package:chrono_sheet/log/util/log_util.dart';
45
import 'package:chrono_sheet/ui/widget_key.dart';
56
import 'package:flutter/material.dart';
67
import 'package:flutter_test/flutter_test.dart';
78

89
import '../../../../../test_common/context/test_context.dart';
910

11+
final _logger = getNamedLogger();
12+
1013
class ManageCategoryScreenDriver {
1114

1215
final WidgetTester tester;
1316

1417
ManageCategoryScreenDriver(this.tester);
1518

1619
Future<void> setCategoryName(String name) async {
20+
_logger.info("setting active category name as '$name'");
1721
final nameField = find.byKey(AppWidgetKey.manageCategoryName);
1822
expect(nameField, findsOneWidget);
1923

@@ -22,7 +26,9 @@ class ManageCategoryScreenDriver {
2226
}
2327

2428
Future<void> selectIcon(String icon) async {
25-
final iconFile = File("${TestContext.current.rootLocalDirPath}/$icon");
29+
final iconPath = "${TestContext.current.rootLocalDirPath}/$icon";
30+
_logger.info("selecting category icon from path $iconPath");
31+
final iconFile = File(iconPath);
2632
if (!iconFile.existsSync()) {
2733
throw AssertionError("icon file with name '$icon' does not exist at path: ${iconFile.path}");
2834
}
@@ -38,6 +44,7 @@ class ManageCategoryScreenDriver {
3844
}
3945

4046
Future<void> saveChanges() async {
47+
_logger.info("saving category changes");
4148
final saveButton = find.byKey(AppWidgetKey.saveCategoryState);
4249
expect(saveButton, findsOneWidget);
4350

integration_test/framework/driver/choose_sheet/choose_sheet_driver.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1+
import 'package:chrono_sheet/log/util/log_util.dart';
12
import 'package:flutter/material.dart';
23
import 'package:flutter_test/flutter_test.dart';
34

45
import '../../../../test_common/context/test_context.dart';
56
import '../../../category/integration_test_common.dart';
67

8+
final _logger = getNamedLogger();
9+
710
class ChooseSheetScreenDriver {
811
final WidgetTester tester;
912

1013
const ChooseSheetScreenDriver(this.tester);
1114

1215
Future<void> selectTestSheet() async {
13-
final fileFinder = find.widgetWithText(ListTile, TestContext.current.testId);
16+
final sheetName = TestContext.current.testId;
17+
final fileFinder = find.widgetWithText(ListTile, sheetName);
1418
await UiVerificationUtil.waitForWidget(
1519
description: "a google sheet created for the current test",
1620
tester: tester,
1721
finder: fileFinder,
1822
);
23+
_logger.info("selected google sheet file '$sheetName'");
24+
1925
await tester.tap(fileFinder);
2026
await tester.pumpAndSettle();
2127
}

integration_test/framework/driver/main/main_screen_driver.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import 'package:chrono_sheet/log/util/log_util.dart';
12
import 'package:chrono_sheet/ui/widget_key.dart';
23
import 'package:flutter_test/flutter_test.dart';
34

5+
final _logger = getNamedLogger();
6+
47
class MainScreenDriver {
58

69
final WidgetTester tester;
710

811
MainScreenDriver(this.tester);
912

10-
Future<void> clickSelectFile() async {
13+
Future<void> clickSelectGoogleFile() async {
14+
_logger.info("clicking 'select google file' widget");
1115
final selectFileWidget = find.byKey(AppWidgetKey.selectFile);
1216
expect(selectFileWidget, findsOneWidget);
1317

@@ -16,6 +20,7 @@ class MainScreenDriver {
1620
}
1721

1822
Future<void> clickAddCategory() async {
23+
_logger.info("clicking 'add category' widget");
1924
final createCategoryButton = find.byKey(AppWidgetKey.createCategory);
2025
expect(createCategoryButton, findsOneWidget);
2126

lib/category/model/category.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import 'package:chrono_sheet/category/model/category_representation.dart';
2+
import 'package:chrono_sheet/log/util/log_util.dart';
23
import 'package:flutter/foundation.dart';
34
import 'package:shared_preferences/shared_preferences.dart';
45

6+
final _logger = getNamedLogger();
7+
58
class _Key {
69
static String getName(String keyPrefix) {
710
return "$keyPrefix.name";
@@ -44,6 +47,7 @@ final class Category implements Comparable<Category> {
4447
await prefs.setString(_Key.getName(keyPrefix), name);
4548
await prefs.setBool(_Key.getPersistedInGoogle(keyPrefix), persistedInGoogle);
4649
await representation.serialize(prefs, keyPrefix);
50+
_logger.fine("stored category $this into a local storage under key prefix '$keyPrefix'");
4751
}
4852

4953
static Future<Category?> deserialiseIfPossible(SharedPreferencesAsync prefs, String keyPrefix) async {

lib/category/service/category_manager.g.dart

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/category/service/category_manager.dart renamed to lib/category/service/shared_category_data_manager.dart

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ final _logger = getNamedLogger();
2222
typedef _CategoriesToInfo = Map<String, IconInfo>;
2323

2424
@Riverpod(keepAlive: true)
25-
CategoryManager categoryManager(Ref ref) {
26-
return CategoryManager();
25+
SharedCategoryDataManager categoryManager(Ref ref) {
26+
return SharedCategoryDataManager();
2727
}
2828

2929
class _Key {
@@ -59,7 +59,7 @@ class CategoryGooglePaths {
5959
static String get picturesDirPath => "$rootDirPathToUse/pictures";
6060
}
6161

62-
class CategoryManager {
62+
class SharedCategoryDataManager {
6363
final _prefs = SharedPreferencesAsync();
6464
final driveService = GoogleDriveService();
6565
DateTime? _startTime;
@@ -75,7 +75,7 @@ class CategoryManager {
7575
final diff = now.difference(start);
7676
if (diff.inMinutes < 10) {
7777
_logger.info(
78-
"skipped picture manager tick because only ${diff.inMinutes} minutes elapsed since the last check",
78+
"skipped category manager tick because only ${diff.inMinutes} minutes elapsed since the last check",
7979
);
8080
return;
8181
}
@@ -84,8 +84,10 @@ class CategoryManager {
8484
var online = await isOnline();
8585
if (!online) {
8686
_logger.info("skipped picture manager tick because the application is offline");
87+
return;
8788
}
8889

90+
_logger.info("checking if we need to sync local and remote categories info");
8991
_startTime = now;
9092
try {
9193
await _handlePendingCategoryRenames();
@@ -106,7 +108,7 @@ class CategoryManager {
106108
}
107109

108110
Future<_CategoriesToInfo> _getRemoteInfo() async {
109-
_logger.info("start downloading remote pictures infos");
111+
_logger.info("start fetching remote categories infos");
110112
final directoryId = await _getGoogleDirectoryId(CategoryGooglePaths.mappingDirPath);
111113
final driveFiles = await driveService.listFiles(directoryId);
112114
final result = <String, IconInfo>{};
@@ -149,7 +151,7 @@ class CategoryManager {
149151

150152
final files = rootDir.listSync();
151153
final Map<String, IconInfo> result = {};
152-
_logger.fine("found ${files.length} category mapping files in directory ${rootDir.path}");
154+
_logger.fine("found ${files.length} category mapping file(s) in directory ${rootDir.path}");
153155
for (final file in files) {
154156
if (file is File) {
155157
final categoryName = p.basename(file.path);
@@ -257,24 +259,28 @@ class CategoryManager {
257259
}
258260

259261
Future<void> onNewCategory(Category category) async {
262+
_logger.fine("got information about new category '$category'");
260263
await category.serialize(_prefs, _Key.getCategory(category.name));
261264
final representation = category.representation;
262265
if (representation is! ImageCategoryRepresentation) {
263-
_logger.fine("skip category change as it doesn't have image representations: $category");
266+
_logger.fine("skip new category processing as it doesn't have image representations: $category");
264267
return;
265268
}
266269
final iconFile = representation.file;
267270
final mappingFile = File("${_getLocalDataDir().path}/${category.name}");
268271
final parentDir = mappingFile.parent;
269272
if (mappingFile.existsSync()) {
270273
mappingFile.deleteSync();
274+
_logger.fine("deleted previous local category mapping file for category '${category.name}': ${mappingFile.path}");
271275
} else if (!parentDir.existsSync()) {
272276
await parentDir.create(recursive: true);
273-
_logger.info("created a directory for storing categories meta info: ${parentDir.path}");
277+
_logger.info("created a local directory for storing categories meta info: ${parentDir.path}");
274278
}
275279
final content = "${iconFile.path},${clockProvider.now().toIso8601String()}";
276280
mappingFile.writeAsStringSync(content);
277-
_logger.info("written '$content' into category meta info file ${mappingFile.path} for category ${category.name}");
281+
_logger.info(
282+
"wrote category meta info for category '${category.name}' into local file ${mappingFile.path}: $content",
283+
);
278284
await tick(true);
279285
}
280286

lib/category/state/categories_state.dart

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:chrono_sheet/category/model/category_representation.dart';
55
import 'package:chrono_sheet/file/state/file_state.dart';
66
import 'package:chrono_sheet/generated/app_localizations.dart';
77
import 'package:chrono_sheet/log/util/log_util.dart';
8-
import 'package:chrono_sheet/category/service/category_manager.dart';
8+
import 'package:chrono_sheet/category/service/shared_category_data_manager.dart';
99
import 'package:chrono_sheet/sheet/model/sheet_model.dart';
1010
import 'package:chrono_sheet/sheet/parser/sheet_parser.dart';
1111
import 'package:chrono_sheet/util/regexp_util.dart';
@@ -91,18 +91,18 @@ class CategoriesStateManager extends _$CategoryStateManager {
9191
if (selectedFile == null) {
9292
return CategoriesState.empty;
9393
}
94-
final cached = await _readCachedCategoryState(selectedFile);
95-
if (cached == null) {
94+
final local = await _readLocalCategoryState(selectedFile);
95+
if (local == null) {
9696
final result = await _parseAndApplyCategoriesFromSheet(selectedFile);
9797
return result.match((error) => CategoriesState(), (newState) => newState);
9898
} else {
99-
_logger.info("found cached category state: $cached");
99+
_logger.info("found local category state: $local");
100100
_parseAndApplyCategoriesFromSheet(selectedFile).then((result) {
101101
result.map((newState) {
102102
state = AsyncValue.data(newState);
103103
});
104104
});
105-
return cached;
105+
return local;
106106
}
107107
}
108108

@@ -117,11 +117,11 @@ class CategoriesStateManager extends _$CategoryStateManager {
117117
(categoryNamesFromFile) async {
118118
_logger.info("fetched remote categories: $categoryNamesFromFile");
119119
final currentState = state;
120-
CategoriesState? cached;
120+
CategoriesState? local;
121121
if (currentState is AsyncData) {
122-
cached = currentState.value;
122+
local = currentState.value;
123123
}
124-
final newCategoryState = await _merge(cached, categoryNamesFromFile);
124+
final newCategoryState = await _merge(local, categoryNamesFromFile);
125125
await _cacheCategoryState(newCategoryState, file);
126126
return Either.right(newCategoryState);
127127
},
@@ -140,7 +140,7 @@ class CategoriesStateManager extends _$CategoryStateManager {
140140
);
141141
}
142142

143-
Future<CategoriesState?> _readCachedCategoryState(GoogleFile file) async {
143+
Future<CategoriesState?> _readLocalCategoryState(GoogleFile file) async {
144144
List<Category> categories = [];
145145
Set<String> usedCategories = {};
146146
for (int i = 0; ; i++) {
@@ -156,7 +156,7 @@ class CategoriesStateManager extends _$CategoryStateManager {
156156
categories.add(category);
157157
}
158158
_logger.info(
159-
"found ${categories.length} cached categories for file ${file.id} (${file.name}): \n${categories.join("\n")}",
159+
"found ${categories.length} local category(ies) for file ${file.id} (${file.name}): \n${categories.join("\n")}",
160160
);
161161
if (categories.isEmpty) {
162162
return null;
@@ -264,12 +264,12 @@ class CategoriesStateManager extends _$CategoryStateManager {
264264
return {s1: _getDefaultRepresentationText(s1), s2: _getDefaultRepresentationText(s2)};
265265
}
266266

267-
Future<CategoriesState> _merge(CategoriesState? cached, List<String> currentCategoryNames) async {
268-
_logger.info("merging cached categories state (\n$cached\n) and current categories ($currentCategoryNames)");
269-
if (currentCategoryNames.isEmpty && (cached?.categories.all((c) => c.persistedInGoogle) ?? true)) {
267+
Future<CategoriesState> _merge(CategoriesState? local, List<String> currentCategoryNames) async {
268+
_logger.info("merging local categories state (\n$local\n) and current categories (\n$currentCategoryNames\n)");
269+
if (currentCategoryNames.isEmpty && (local?.categories.all((c) => c.persistedInGoogle) ?? true)) {
270270
return CategoriesState.empty;
271271
}
272-
if (cached == null) {
272+
if (local == null) {
273273
List<Category> categories = await Future.wait(
274274
currentCategoryNames.map((name) async {
275275
return await _getCategoryByName(name);
@@ -279,12 +279,12 @@ class CategoriesStateManager extends _$CategoryStateManager {
279279
final selected = categories.first;
280280
return CategoriesState(selected: selected, categories: categories);
281281
}
282-
List<Category> sortedCategories = List.of(cached.categories);
282+
List<Category> sortedCategories = List.of(local.categories);
283283
sortedCategories.removeWhere(
284284
(category) => !currentCategoryNames.contains(category.name) && category.persistedInGoogle,
285285
);
286-
final Set<String> cachedCategoryNames = Set.of(cached.categories.map((c) => c.name));
287-
final categoryNamesToAdd = currentCategoryNames.where((name) => !cachedCategoryNames.contains(name));
286+
final Set<String> localCategoryNames = Set.of(local.categories.map((c) => c.name));
287+
final categoryNamesToAdd = currentCategoryNames.where((name) => !localCategoryNames.contains(name));
288288
final categoriesToAdd = await Future.wait(
289289
categoryNamesToAdd.map((name) async {
290290
return await _getCategoryByName(name);
@@ -294,7 +294,7 @@ class CategoriesStateManager extends _$CategoryStateManager {
294294

295295
sortedCategories = ensureNoDuplicateTextRepresentations(sortedCategories);
296296

297-
Category? selected = cached.selected;
297+
Category? selected = local.selected;
298298
if (selected == null || !currentCategoryNames.contains(selected.name)) {
299299
selected = sortedCategories.first;
300300
}
@@ -334,7 +334,7 @@ class CategoriesStateManager extends _$CategoryStateManager {
334334
for (int i = 0; i < categories.length; i++) {
335335
await _prefs.setString(_Key.getFileCategoryPrefix(fileToUse, i), categories[i].name);
336336
}
337-
_logger.info("cached categories state for file ${fileToUse.id} (${fileToUse.name}): $state");
337+
_logger.info("local categories state for file ${fileToUse.id} (${fileToUse.name}): $state");
338338
return ManageCategoryResult.success;
339339
}
340340

@@ -360,6 +360,7 @@ class CategoriesStateManager extends _$CategoryStateManager {
360360
}
361361

362362
Future<ManageCategoryResult> addNewCategory(Category category) async {
363+
_logger.info("got a request to add category $category");
363364
final currentState = await future;
364365
final withConflictingName = _findCategoryWithName(currentState, category.name);
365366
if (withConflictingName != null) {
@@ -374,7 +375,7 @@ class CategoriesStateManager extends _$CategoryStateManager {
374375
state = AsyncValue.data(newState);
375376
final result = await _cacheCategoryState(newState);
376377
if (result == ManageCategoryResult.success) {
377-
_logger.info("categories state after adding new category '$category': $newState");
378+
_logger.info("successfully added category $category");
378379
}
379380

380381
ref.read(categoryManagerProvider).onNewCategory(category);

0 commit comments

Comments
 (0)