diff --git a/lib/common_widgets/tag_dialog.dart b/lib/common_widgets/tag_dialog.dart index a0f705a..f76e581 100644 --- a/lib/common_widgets/tag_dialog.dart +++ b/lib/common_widgets/tag_dialog.dart @@ -12,7 +12,7 @@ class Tag { }); @override - String toString() => name; + String toString() => '$name ($selected)'; } class TagDialog extends StatefulWidget { diff --git a/lib/domain/todo/todo_model.dart b/lib/domain/todo/todo_model.dart index 8533c03..09e21c5 100644 --- a/lib/domain/todo/todo_model.dart +++ b/lib/domain/todo/todo_model.dart @@ -1,5 +1,7 @@ +import 'dart:convert'; import 'dart:math'; +import 'package:crypto/crypto.dart'; import 'package:equatable/equatable.dart'; import 'package:ntodotxt/exceptions/exceptions.dart'; @@ -106,10 +108,7 @@ class Todo extends Equatable { // Prevent +, @ at the beginning and additional ':' within. static final RegExp patternKeyValue = RegExp(r'^([^\+\@].*[^:\s]):(.*[^:\s])$'); // @todo: a:b failed - static final RegExp patternId = RegExp(r'^id:[a-zA-Z0-9\-]+$'); - /// Unique [id] - /// [id] is mandatory. final String id; /// Whether the [Todo] is completed. @@ -133,8 +132,6 @@ class Todo extends Equatable { /// Defaults to null (unset). final String? _description; - String get fmtId => 'id:$id'; - /// Whether the [Todo] is completed. /// Defaults to false. bool get completion => _completion ?? false; @@ -172,7 +169,6 @@ class Todo extends Equatable { String get fmtDescription { final List descriptionList = []; for (String item in description.split(' ')) { - if (patternId.hasMatch(item)) continue; if (matchProject(item)) continue; if (matchContext(item)) continue; if (matchKeyValue(item)) continue; @@ -248,7 +244,6 @@ class Todo extends Equatable { if (matchKeyValue(item)) { List kvSplitted = item.split(':'); if (kvSplitted.length > 2) continue; - if (kvSplitted[0] == 'id') continue; // Exclude id here. keyValues.add(item.toLowerCase()); } } @@ -358,6 +353,7 @@ class Todo extends Equatable { } factory Todo.fromString({ + String? id, required String value, }) { final todoStr = _trim(value); @@ -422,7 +418,7 @@ class Todo extends Equatable { } return Todo( - id: _str2Id(fullDescriptionList) ?? Todo.genId(), + id: id ?? Todo.genId(), completion: completion, priority: priority, completionDate: completionDate, @@ -487,7 +483,6 @@ class Todo extends Equatable { @override List get props => [ - id, completion, completionDate, priority, @@ -496,26 +491,25 @@ class Todo extends Equatable { ]; @override - String toString({ - bool includeId = true, - }) { + String toString() { final List items = [ fmtCompletion, fmtCompletionDate, fmtPriority, fmtCreationDate, description, - if (includeId) fmtId, ]..removeWhere((value) => value.isEmpty); return items.join(' '); } - static String genId({int len = 10}) { + static String genId({int len = 32}) { final Random r = Random(); const chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; - return List.generate(len, (index) => chars[r.nextInt(chars.length)]).join(); + final String randomId = + List.generate(len, (index) => chars[r.nextInt(chars.length)]).join(); + return sha256.convert(utf8.encode(randomId)).toString(); } static DateTime? str2date(String value) { @@ -599,25 +593,16 @@ class Todo extends Equatable { return Priority.none; } - /// Trim projects, contexts and key-values from description. static String _str2description(List strList) { final List descriptionList = []; for (var item in strList) { - if (patternId.hasMatch(item)) continue; - descriptionList.add(item); - } - - return descriptionList.join(' '); - } - - static String? _str2Id(List strList) { - for (var item in strList) { - if (patternId.hasMatch(item)) { - final List splittedId = item.split(':'); - return splittedId[1]; + if (matchProject(item) || matchContext(item) || matchKeyValue(item)) { + descriptionList.add(item.toLowerCase()); + } else { + descriptionList.add(item); } } - return null; + return descriptionList.join(' '); } } diff --git a/pubspec.lock b/pubspec.lock index 6ee1853..4de9677 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -90,7 +90,7 @@ packages: source: hosted version: "3.1.1" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab diff --git a/pubspec.yaml b/pubspec.yaml index 2ce1d32..5f97bfb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: flutter: sdk: flutter collection: ^1.17.2 + crypto: ^3.0.3 cupertino_icons: ^1.0.6 dio: ^5.1.0 equatable: ^2.0.5 diff --git a/test/data/todo/todo_list_api_test.dart b/test/data/todo/todo_list_api_test.dart index c244ce0..7df2b7a 100644 --- a/test/data/todo/todo_list_api_test.dart +++ b/test/data/todo/todo_list_api_test.dart @@ -30,8 +30,7 @@ void main() { ); }); test('initial file with initial todo', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); + const String todoStr = '2023-11-23 Code something'; await file.writeAsString(todoStr, flush: true); final LocalTodoListApi api = LocalTodoListApi(todoFile: file); @@ -40,7 +39,7 @@ void main() { await expectLater( repository.getTodoList(), emitsInOrder([ - [todo], + [Todo.fromString(value: todoStr)], ]), ); }); @@ -52,10 +51,6 @@ void main() { '2023-12-02 TodoD due:2023-12-05 id:4', '2023-11-11 TodoE id:5', ]; - List todoList = [ - for (var s in todoListStr) Todo.fromString(value: s) - ]; - await file.writeAsString(todoListStr.join('\n'), flush: true); final LocalTodoListApi api = LocalTodoListApi(todoFile: file); @@ -65,13 +60,7 @@ void main() { repository.getTodoList(), emitsInOrder( [ - [ - todoList[0], - todoList[1], - todoList[2], - todoList[3], - todoList[4], - ], + [for (var s in todoListStr) Todo.fromString(value: s)], ], ), ); @@ -79,32 +68,14 @@ void main() { }); group('saveTodo()', () { - test('create new todo without id', () async { - const String todoStr = '2023-11-23 Code something'; - final Todo todo = Todo.fromString(value: todoStr); - + test('create new todo', () async { final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); - repository.saveTodo(todo); - - await expectLater( - repository.getTodoList(), - emitsInOrder([ - [todo], - ]), + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', ); - await repository.writeToSource(); - expect(await file.readAsLines(), ['$todoStr id:${todo.id}']); - }); - - test('create new todo with id', () async { - const String todoStr = - '2023-11-23 Code something id:d181bdf4-3c0b-483c-a350-62db3c19ff36'; - final Todo todo = Todo.fromString(value: todoStr); - - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); - final TodoListRepository repository = TodoListRepository(api); repository.saveTodo(todo); await expectLater( @@ -115,20 +86,22 @@ void main() { ); await repository.writeToSource(); - expect(await file.readAsLines(), [todoStr]); + expect(await file.readAsLines(), [todo.toString()]); }); test('update existing todo', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); - // Update existing todo. - final Todo todo2 = todo.copyWith( - description: 'Code something other', - ); - await file.writeAsString(todoStr, flush: true); - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); - repository.saveTodo(todo2); + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', + ); + final Todo todo2 = Todo.fromString( + id: '1', + value: '2023-11-23 Code something other', + ); + + repository.saveTodo(todo); + repository.saveTodo(todo2); // Update existing one. await expectLater( repository.getTodoList(), @@ -140,64 +113,46 @@ void main() { await repository.writeToSource(); expect( await file.readAsLines(), - ['2023-11-23 Code something other id:1'], + [todo2.toString()], ); }); test('update/save non-existing todo', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); - const String todoStr2 = '2023-11-23 Code something other id:2'; - final Todo todo2 = Todo.fromString(value: todoStr2); - await file.writeAsString(todoStr, flush: true); - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); - repository.saveTodo(todo2); - - await expectLater( - repository.getTodoList(), - emitsInOrder([ - [todo, todo2], - ]), + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', + ); + final Todo todo2 = Todo.fromString( + id: '2', + value: '2023-11-23 Code something other', ); - await repository.writeToSource(); - expect(await file.readAsLines(), [todoStr, todoStr2]); - }); - test('partial update', () async { - const String todoStr = '2023-11-23 Code something id:1'; - const String todoStr2 = '2023-11-23 Code something other id:1'; - final Todo todo = Todo.fromString(value: todoStr); - final Todo todo2 = Todo.fromString(value: todoStr2); - // Get diff for changes. - final Todo todoDiff = todo.copyDiff(priority: Priority.A); - // Simulate changes - await file.writeAsString(todoStr2, flush: true); - - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); - final TodoListRepository repository = TodoListRepository(api); - repository.saveTodo(todoDiff); + repository.saveTodo(todo); + repository.saveTodo(todo2); // Update non-existing one. await expectLater( repository.getTodoList(), emitsInOrder([ - [todo2.copyWith(priority: Priority.A)], + [todo, todo2], ]), ); await repository.writeToSource(); - expect(await file.readAsLines(), ['(A) $todoStr2']); + expect(await file.readAsLines(), [todo.toString(), todo2.toString()]); }); }); group('deleteTodo()', () { test('delete existing todo', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); - await file.writeAsString(todoStr, flush: true); - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', + ); + + repository.saveTodo(todo); repository.deleteTodo(todo); await expectLater( @@ -211,14 +166,18 @@ void main() { expect(await file.readAsLines(), []); }); test('delete non-existing todo', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); - const String todoStr2 = '2023-11-23 Code something other id:2'; - final Todo todo2 = Todo.fromString(value: todoStr2); - await file.writeAsString(todoStr, flush: true); - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', + ); + final Todo todo2 = Todo.fromString( + id: '2', + value: '2023-11-23 Code something other', + ); + + repository.saveTodo(todo); repository.deleteTodo(todo2); // Delete non-existing todo. await expectLater( @@ -235,18 +194,19 @@ void main() { group('saveMultipleTodos()', () { test('update todos', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); - const String todoStr2 = '2023-11-23 Code something other id:2'; - final Todo todo2 = Todo.fromString(value: todoStr2); - - await file.writeAsString( - [todoStr, todoStr2].join(Platform.lineTerminator), - flush: true, - ); - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', + ); + final Todo todo2 = Todo.fromString( + id: '2', + value: '2023-11-23 Code something other', + ); + + repository.saveTodo(todo); + repository.saveTodo(todo2); await expectLater( repository.getTodoList(), @@ -287,18 +247,19 @@ void main() { group('deleteMultipleTodos()', () { test('delete todos', () async { - const String todoStr = '2023-11-23 Code something id:1'; - final Todo todo = Todo.fromString(value: todoStr); - const String todoStr2 = '2023-11-23 Code something other id:2'; - final Todo todo2 = Todo.fromString(value: todoStr2); - - await file.writeAsString( - [todo, todo2].join(Platform.lineTerminator), - flush: true, - ); - final LocalTodoListApi api = LocalTodoListApi(todoFile: file); final TodoListRepository repository = TodoListRepository(api); + final Todo todo = Todo.fromString( + id: '1', + value: '2023-11-23 Code something', + ); + final Todo todo2 = Todo.fromString( + id: '2', + value: '2023-11-23 Code something other', + ); + + repository.saveTodo(todo); + repository.saveTodo(todo2); await expectLater( repository.getTodoList(), diff --git a/test/domain/todo/todo_model_test.dart b/test/domain/todo/todo_model_test.dart index 4101b40..9301b11 100644 --- a/test/domain/todo/todo_model_test.dart +++ b/test/domain/todo/todo_model_test.dart @@ -7,21 +7,27 @@ void main() { group('todo Todo()', () { group('completion & completionDate', () { test('initial incompleted', () { - final todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.completion, false); expect(todo.completionDate, null); }); test('initial completed', () { final DateTime now = DateTime.now(); - final todo = Todo(completion: true, description: 'Write some tests'); + final Todo todo = Todo( + completion: true, + description: 'Write some tests', + ); expect(todo.completion, true); expect(todo.completionDate, DateTime(now.year, now.month, now.day)); }); test('initial completed & completionDate', () { - final todo = Todo( - completion: true, - completionDate: DateTime(1970, 1, 1), - description: 'Write some tests'); + final Todo todo = Todo( + completion: true, + completionDate: DateTime(1970, 1, 1), + description: 'Write some tests', + ); expect(todo.completion, true); expect(todo.completionDate, DateTime(1970, 1, 1)); }); @@ -29,11 +35,13 @@ void main() { group('priority', () { test('no initial priority', () { - final todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.priority, Priority.none); }); test('with initial priority', () { - final todo = Todo( + final Todo todo = Todo( priority: Priority.A, description: 'Write some tests', ); @@ -44,56 +52,75 @@ void main() { group('creationDate', () { test('no initial creationDate', () { final DateTime now = DateTime.now(); - final todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.creationDate, DateTime(now.year, now.month, now.day)); }); test('with initial creationDate', () { final DateTime now = DateTime.now(); - final todo = Todo(creationDate: now, description: 'Write some tests'); + final Todo todo = Todo( + creationDate: now, + description: 'Write some tests', + ); expect(todo.creationDate, DateTime(now.year, now.month, now.day)); }); }); group('description', () { test('no initial description', () { - final todo = Todo(); + final Todo todo = Todo(); expect(todo.description, ''); }); test('with initial description', () { - final todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.description, 'Write some tests'); }); }); group('projects', () { test('no initial projects', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.projects, []); }); test('with initial projects', () { - final Todo todo = Todo(description: 'Write some tests +project1'); + final Todo todo = Todo( + description: 'Write some tests +project1', + ); expect(todo.projects, {'project1'}); }); }); group('contexts', () { test('no initial contexts', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.contexts, []); }); test('with initial contexts', () { - final Todo todo = Todo(description: 'Write some tests @context1'); + final Todo todo = Todo( + description: 'Write some tests @context1', + ); expect(todo.contexts, {'context1'}); }); }); group('keyValues', () { test('no initial keyValues', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); expect(todo.keyValues, []); }); test('with initial keyValues', () { - final Todo todo = Todo(description: 'Write some tests key:value'); + final Todo todo = Todo( + description: 'Write some tests key:value', + ); expect(todo.keyValues, {'key:value'}); }); }); @@ -103,21 +130,27 @@ void main() { group('completion & completionDate', () { test('set completion', () { final DateTime now = DateTime.now(); - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(completion: true); expect(todo2.completion, true); expect(todo2.completionDate, DateTime(now.year, now.month, now.day)); }); test('set completion & completionDate', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith( completion: true, completionDate: DateTime(1970, 1, 1)); expect(todo2.completion, true); expect(todo2.completionDate, DateTime(1970, 1, 1)); }); test('unset completion', () { - final Todo todo = - Todo(completion: true, description: 'Write some tests'); + final Todo todo = Todo( + completion: true, + description: 'Write some tests', + ); final todo2 = todo.copyWith(completion: false); expect(todo2.completion, false); expect(todo2.completionDate, null); @@ -126,7 +159,9 @@ void main() { group('priority', () { test('set priority', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(priority: Priority.A); expect(todo2.priority, Priority.A); }); @@ -144,12 +179,16 @@ void main() { group('description', () { test('set description', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(description: 'Write more tests'); expect(todo2.description, 'Write more tests'); }); test('unset description', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(description: ''); expect(todo2.description, ''); }); @@ -157,12 +196,16 @@ void main() { group('projects', () { test('set projects', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(description: 'Write some tests +project2'); expect(todo2.projects, {'project2'}); }); test('unset projects', () { - final Todo todo = Todo(description: 'Write some tests +project2'); + final Todo todo = Todo( + description: 'Write some tests +project2', + ); final todo2 = todo.copyWith(description: 'Write some tests'); expect(todo2.projects, []); }); @@ -170,12 +213,16 @@ void main() { group('contexts', () { test('set contexts', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(description: 'Write some tests @context2'); expect(todo2.contexts, {'context2'}); }); test('unset contexts', () { - final Todo todo = Todo(description: 'Write some tests @context2'); + final Todo todo = Todo( + description: 'Write some tests @context2', + ); final todo2 = todo.copyWith(description: 'Write some tests'); expect(todo2.contexts, []); }); @@ -183,12 +230,16 @@ void main() { group('keyValues', () { test('set keyValues', () { - final Todo todo = Todo(description: 'Write some tests'); + final Todo todo = Todo( + description: 'Write some tests', + ); final todo2 = todo.copyWith(description: 'Write some tests key:value'); expect(todo2.keyValues, {'key:value'}); }); test('unset keyValues', () { - final Todo todo = Todo(description: 'Write some tests key:value'); + final Todo todo = Todo( + description: 'Write some tests key:value', + ); final todo2 = todo.copyWith(description: 'Write some tests'); expect(todo2.keyValues, []); }); @@ -813,7 +864,7 @@ void main() { final todo = Todo.fromString( value: value, ); - expect(todo.toString(), '$value id:${todo.id}'); + expect(todo.toString(), value); }); test('full todo with multiple whitespace', () { final todo = Todo.fromString( @@ -821,7 +872,7 @@ void main() { 'x 2022-11-16 (A) 2022-11-01 Write some tests +project @context due:2022-12-31', ); expect(todo.toString(), - 'x 2022-11-16 (A) 2022-11-01 Write some tests +project @context due:2022-12-31 id:${todo.id}'); + 'x 2022-11-16 (A) 2022-11-01 Write some tests +project @context due:2022-12-31'); }); }); } diff --git a/test/presentation/todo/states/todo_cubit_test.dart b/test/presentation/todo/states/todo_cubit_test.dart index 022d214..b93ed7a 100644 --- a/test/presentation/todo/states/todo_cubit_test.dart +++ b/test/presentation/todo/states/todo_cubit_test.dart @@ -28,7 +28,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, completion: true, description: todo.description, ), @@ -44,7 +43,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: todo.description, ), ), @@ -59,7 +57,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, completion: true, description: todo.description, ), @@ -78,7 +75,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write more tests', ), ), @@ -96,7 +92,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, priority: Priority.A, description: todo.description, ), @@ -114,7 +109,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, priority: Priority.B, description: todo.description, ), @@ -129,7 +123,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, priority: Priority.none, description: todo.description, ), @@ -144,7 +137,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, priority: Priority.none, description: todo.description, ), @@ -163,7 +155,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1', ), ), @@ -178,7 +169,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1 +project2', ), ), @@ -194,7 +184,6 @@ void main() { TodoError( message: 'Invalid project tag: project 2', todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -209,7 +198,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1', ), ), @@ -224,7 +212,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1', ), ), @@ -239,7 +226,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1 +project2', ), ), @@ -254,7 +240,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project2', ), ), @@ -270,7 +255,6 @@ void main() { TodoError( message: 'Invalid project tag: project 2', todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -285,7 +269,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1 +project2', ), ), @@ -300,7 +283,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests +project1 +project2', ), ), @@ -317,7 +299,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -333,7 +314,6 @@ void main() { TodoError( message: 'Invalid project tag: project 1', todo: Todo( - id: todo.id, description: 'Write some tests +project1', ), ), @@ -348,7 +328,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -368,7 +347,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1', ), ), @@ -383,7 +361,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1 @context2', ), ), @@ -399,7 +376,6 @@ void main() { TodoError( message: 'Invalid context tag: context 2', todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -414,7 +390,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1', ), ), @@ -429,7 +404,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1', ), ), @@ -444,7 +418,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1 @context2', ), ), @@ -459,7 +432,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context2', ), ), @@ -475,7 +447,6 @@ void main() { TodoError( message: 'Invalid context tag: context 2', todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -490,7 +461,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1 @context2', ), ), @@ -505,7 +475,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests @context1 @context2', ), ), @@ -522,7 +491,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -538,7 +506,6 @@ void main() { TodoError( message: 'Invalid context tag: context 1', todo: Todo( - id: todo.id, description: 'Write some tests @context1', ), ), @@ -553,7 +520,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -573,7 +539,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests key:val', ), ), @@ -588,7 +553,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:bar key:val', ), ), @@ -604,7 +568,6 @@ void main() { TodoError( message: 'Invalid key value tag: key_val', todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -619,7 +582,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:bar', ), ), @@ -634,7 +596,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:bar', ), ), @@ -649,7 +610,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:new', ), ), @@ -664,7 +624,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests key1:val1 key2:val2', ), ), @@ -679,7 +638,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests key2:val2', ), ), @@ -695,7 +653,6 @@ void main() { TodoError( message: 'Invalid key value tag: key2_val2', todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -710,7 +667,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:bar key1:val1', ), ), @@ -725,7 +681,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:bar key1:val1', ), ), @@ -740,7 +695,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests foo:new key1:val1', ), ), @@ -757,7 +711,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests', ), ), @@ -773,7 +726,6 @@ void main() { TodoError( message: 'Invalid key value tag: key_val', todo: Todo( - id: todo.id, description: 'Write some tests foo:bar', ), ), @@ -788,7 +740,6 @@ void main() { bloc.state, TodoSuccess( todo: Todo( - id: todo.id, description: 'Write some tests', ), ), diff --git a/test/presentation/todo/states/todo_list_bloc_test.dart b/test/presentation/todo/states/todo_list_bloc_test.dart index 579161a..1600c14 100644 --- a/test/presentation/todo/states/todo_list_bloc_test.dart +++ b/test/presentation/todo/states/todo_list_bloc_test.dart @@ -22,15 +22,12 @@ void main() { fs = MemoryFileSystem(); file = fs.file('todo.test'); await file.create(); + await file.writeAsString('', flush: true); // Empty file + api = LocalTodoListApi(todoFile: file); + repository = TodoListRepository(api); }); group('Initial', () { - setUp(() async { - await file.writeAsString('', flush: true); // Empty file - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); - }); - test('initial state', () { final TodoListBloc todoListBloc = TodoListBloc(repository: repository); expect(todoListBloc.state is TodoListLoading, true); @@ -39,13 +36,6 @@ void main() { }); group('TodoListSubscriptionRequested', () { - setUp(() async { - todo = Todo(description: 'Write some tests'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); - }); - test('initial state', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc @@ -54,10 +44,13 @@ void main() { await expectLater( bloc.stream, - emitsInOrder([ - TodoListLoading(todoList: [todo]), - TodoListSuccess(todoList: [todo]), - ]), + emitsInOrder( + [ + emitsThrough( + const TodoListSuccess(todoList: []), + ), + ], + ), ); }); }); @@ -66,27 +59,36 @@ void main() { group('completion', () { setUp(() async { todo = Todo( + id: '1', completion: false, description: 'Write some tests', ); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(completion: true), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(completion: true), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [todo.copyWith(completion: true)], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(completion: true)], + ), + ), + ], ), ); }); @@ -95,20 +97,25 @@ void main() { group('priority', () { setUp(() async { todo = Todo( + id: '1', priority: Priority.A, description: 'Write some tests', ); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(priority: Priority.B), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(priority: Priority.B), + ), + ); await expectLater( bloc.stream, @@ -123,16 +130,27 @@ void main() { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(priority: Priority.none), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(priority: Priority.none), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [todo.copyWith(priority: Priority.none)], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(priority: Priority.none)], + ), + ), + ], ), ); }); @@ -140,25 +158,36 @@ void main() { group('description', () { setUp(() async { - todo = Todo(description: 'Write some tests'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); + todo = Todo( + id: '1', + description: 'Write some tests', + ); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(description: 'Write more tests'), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(description: 'Write more tests'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [todo.copyWith(description: 'Write more tests')], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(description: 'Write more tests')], + ), + ), + ], ), ); }); @@ -166,30 +195,41 @@ void main() { group('projects', () { setUp(() async { - todo = Todo(description: 'Write some tests +project1'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); + todo = Todo( + id: '1', + description: 'Write some tests +project1', + ); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith( - description: 'Write some tests +project1 +project2'), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith( + description: 'Write some tests +project1 +project2'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [ - todo.copyWith( - description: 'Write some tests +project1 +project2', - ) - ], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [ + todo.copyWith( + description: 'Write some tests +project1 +project2', + ) + ], + ), + ), + ], ), ); }); @@ -197,19 +237,31 @@ void main() { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(description: 'Write some tests'))); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(description: 'Write some tests'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [ - todo.copyWith( - description: 'Write some tests', - ) - ], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [ + todo.copyWith( + description: 'Write some tests', + ) + ], + ), + ), + ], ), ); }); @@ -217,30 +269,41 @@ void main() { group('contexts', () { setUp(() async { - todo = Todo(description: 'Write some tests @context1'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); + todo = Todo( + id: '1', + description: 'Write some tests @context1', + ); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith( - description: 'Write some tests @context1 @context2'), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith( + description: 'Write some tests @context1 @context2'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [ - todo.copyWith( - description: 'Write some tests @context1 @context2', - ) - ], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [ + todo.copyWith( + description: 'Write some tests @context1 @context2', + ) + ], + ), + ), + ], ), ); }); @@ -248,19 +311,31 @@ void main() { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(description: 'Write some tests'))); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(description: 'Write some tests'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [ - todo.copyWith( - description: 'Write some tests', - ) - ], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [ + todo.copyWith( + description: 'Write some tests', + ) + ], + ), + ), + ], ), ); }); @@ -268,30 +343,41 @@ void main() { group('key values', () { setUp(() async { - todo = Todo(description: 'Write some tests foo:bar'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); + todo = Todo( + id: '1', + description: 'Write some tests foo:bar', + ); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: - todo.copyWith(description: 'Write some tests foo:bar key:val'), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith( + description: 'Write some tests foo:bar key:val'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [ - todo.copyWith( - description: 'Write some tests foo:bar key:val', - ) - ], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [ + todo.copyWith( + description: 'Write some tests foo:bar key:val', + ) + ], + ), + ), + ], ), ); }); @@ -299,20 +385,31 @@ void main() { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoSubmitted( - todo: todo.copyWith(description: 'Write some tests'), - )); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoSubmitted( + todo: todo.copyWith(description: 'Write some tests'), + ), + ); await expectLater( bloc.stream, - emitsThrough( - TodoListSuccess( - todoList: [ - todo.copyWith( - description: 'Write some tests', - ) - ], - ), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [ + todo.copyWith( + description: 'Write some tests', + ) + ], + ), + ), + ], ), ); }); @@ -324,110 +421,113 @@ void main() { group('TodoListTodoCompletionToggled', () { group('toggle to completed', () { setUp(() async { - todo = Todo(description: 'Write some tests'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); + todo = Todo( + id: '1', + description: 'Write some tests', + ); }); test('set', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoCompletionToggled(todo: todo, completion: true)); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoCompletionToggled(todo: todo, completion: true), + ); await expectLater( bloc.stream, - emitsInOrder([ - // Initial & TodoListSubscriptionRequested - TodoListLoading(todoList: [todo]), - // TodoListTodoCompletionToggled start - TodoListLoading( - todoList: [todo.copyWith(completion: true)], - ), - // TodoListTodoCompletionToggled finished - TodoListSuccess( - todoList: [todo.copyWith(completion: true)], - ), - ]), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(completion: true)], + ), + ), + ], + ), ); }); test('set (not exists)', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); - Todo todo2 = - Todo(description: 'Write more tests'); // Generate new uuid (id) bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoCompletionToggled(todo: todo2, completion: true)); + ..add( + TodoListTodoCompletionToggled(todo: todo, completion: true), + ); await expectLater( bloc.stream, - emitsInOrder([ - // Initial & TodoListSubscriptionRequested - TodoListLoading(todoList: [todo]), - // TodoListTodoCompletionToggled start - TodoListLoading( - todoList: [todo, todo2.copyWith(completion: true)], - ), - // TodoListTodoCompletionToggled finished - TodoListSuccess( - todoList: [todo, todo2.copyWith(completion: true)], - ), - ]), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(completion: true)], + ), + ), + ], + ), ); }); }); group('toggle to incompleted', () { setUp(() async { - todo = Todo(completion: true, description: 'Write some tests'); - await file.writeAsString(todo.toString(), flush: true); - api = LocalTodoListApi(todoFile: file); - repository = TodoListRepository(api); + todo = Todo( + id: '1', + completion: true, + description: 'Write some tests', + ); }); test('unset', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoCompletionToggled(todo: todo, completion: false)); + ..add( + TodoListTodoSubmitted( + todo: todo, + ), + ) + ..add( + TodoListTodoCompletionToggled(todo: todo, completion: false), + ); await expectLater( bloc.stream, - emitsInOrder([ - // Initial & TodoListSubscriptionRequested - TodoListLoading(todoList: [todo]), - // TodoListTodoCompletionToggled start - TodoListLoading( - todoList: [todo.copyWith(completion: false)], - ), - // TodoListTodoCompletionToggled finished - TodoListSuccess( - todoList: [todo.copyWith(completion: false)], - ), - ]), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(completion: false)], + ), + ), + ], + ), ); }); test('unset (not exists)', () async { final TodoListBloc bloc = TodoListBloc(repository: repository); - Todo todo2 = - Todo(description: 'Write more tests'); // Generate new uuid (id) bloc ..add(const TodoListSubscriptionRequested()) - ..add(TodoListTodoCompletionToggled(todo: todo2, completion: false)); + ..add( + TodoListTodoCompletionToggled(todo: todo, completion: false), + ); await expectLater( bloc.stream, - emitsInOrder([ - // Initial & TodoListSubscriptionRequested - TodoListLoading(todoList: [todo]), - // TodoListTodoCompletionToggled start - TodoListLoading( - todoList: [todo, todo2.copyWith(completion: false)], - ), - // TodoListTodoCompletionToggled finished - TodoListSuccess( - todoList: [todo, todo2.copyWith(completion: false)], - ), - ]), + emitsInOrder( + [ + emitsThrough( + TodoListSuccess( + todoList: [todo.copyWith(completion: false)], + ), + ), + ], + ), ); }); });