Initial commit

This commit is contained in:
Anton Stubenbord
2022-10-30 14:15:37 +01:00
commit cb797df7d2
272 changed files with 16278 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_paperless_mobile/features/documents/bloc/documents_cubit.dart';
import 'package:flutter_paperless_mobile/features/documents/bloc/documents_state.dart';
import 'package:flutter_paperless_mobile/features/documents/model/document.model.dart';
import 'package:flutter_paperless_mobile/features/documents/model/document_filter.dart';
import 'package:flutter_paperless_mobile/features/documents/model/paged_search_result.dart';
import 'package:flutter_paperless_mobile/features/documents/repository/document_repository.dart';
import 'package:flutter_paperless_mobile/features/labels/correspondent/model/correspondent.model.dart';
import 'package:flutter_paperless_mobile/features/labels/document_type/model/document_type.model.dart';
import 'package:flutter_paperless_mobile/features/labels/tags/model/tag.model.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import '../../utils.dart';
@GenerateNiceMocks([MockSpec<DocumentRepository>()])
import 'documents_cubit_test.mocks.dart';
void main() async {
TestWidgetsFlutterBinding.ensureInitialized();
final List<DocumentModel> documents = List.unmodifiable(
await loadCollection("test/fixtures/documents/documents.json", DocumentModel.fromJson),
);
final List<Tag> tags = List.unmodifiable(
await loadCollection("test/fixtures/tags/tags.json", Tag.fromJson),
);
final List<Correspondent> correspondents = List.unmodifiable(
await loadCollection(
"test/fixtures/correspondents/correspondents.json", Correspondent.fromJson),
);
final List<DocumentType> documentTypes = List.unmodifiable(
await loadCollection("test/fixtures/document_types/document_types.json", DocumentType.fromJson),
);
final MockDocumentRepository documentRepository = MockDocumentRepository();
group("Test DocumentsCubit reloadDocuments", () {
test("Assert correct initial state", () {
expect(DocumentsCubit(documentRepository).state, DocumentsState.initial);
});
blocTest<DocumentsCubit, DocumentsState>(
"Load documents shall emit new state containing the found documents",
setUp: () => when(documentRepository.find(any)).thenAnswer(
(_) async => PagedSearchResult(
count: 10,
next: null,
previous: null,
results: documents,
),
),
build: () => DocumentsCubit(documentRepository),
seed: () => DocumentsState.initial,
act: (bloc) => bloc.loadDocuments(),
expect: () => [
DocumentsState(
isLoaded: true,
value: [
PagedSearchResult(
count: 10,
next: null,
previous: null,
results: documents,
),
],
filter: DocumentFilter.initial)
],
verify: (bloc) => verify(documentRepository.find(any)).called(1),
);
blocTest<DocumentsCubit, DocumentsState>(
"Reload documents shall emit new state containing the same documents as before",
setUp: () => when(documentRepository.find(any)).thenAnswer(
(_) async => PagedSearchResult(
count: 10,
next: null,
previous: null,
results: documents,
),
),
build: () => DocumentsCubit(documentRepository),
seed: () => DocumentsState.initial,
act: (bloc) => bloc.loadDocuments(),
expect: () => [
DocumentsState(
isLoaded: true,
value: [
PagedSearchResult(
count: 10,
next: null,
previous: null,
results: documents,
),
],
filter: DocumentFilter.initial)
],
verify: (bloc) => verify(documentRepository.find(any)).called(1),
);
});
}
@@ -0,0 +1,293 @@
// Mocks generated by Mockito 5.3.2 from annotations
// in flutter_paperless_mobile/test/src/bloc/documents_cubit_test.dart.
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i6;
import 'dart:typed_data' as _i7;
import 'package:flutter_paperless_mobile/features/documents/model/document.model.dart'
as _i2;
import 'package:flutter_paperless_mobile/features/documents/model/document_filter.dart'
as _i8;
import 'package:flutter_paperless_mobile/features/documents/model/document_meta_data.model.dart'
as _i4;
import 'package:flutter_paperless_mobile/features/documents/model/paged_search_result.dart'
as _i3;
import 'package:flutter_paperless_mobile/features/documents/model/similar_document.model.dart'
as _i9;
import 'package:flutter_paperless_mobile/features/documents/repository/document_repository.dart'
as _i5;
import 'package:mockito/mockito.dart' as _i1;
// 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: 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 _FakeDocumentModel_0 extends _i1.SmartFake implements _i2.DocumentModel {
_FakeDocumentModel_0(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakePagedSearchResult_1<T> extends _i1.SmartFake
implements _i3.PagedSearchResult<T> {
_FakePagedSearchResult_1(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeDocumentMetaData_2 extends _i1.SmartFake
implements _i4.DocumentMetaData {
_FakeDocumentMetaData_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [DocumentRepository].
///
/// See the documentation for Mockito's code generation for more information.
class MockDocumentRepository extends _i1.Mock
implements _i5.DocumentRepository {
@override
_i6.Future<void> create(
_i7.Uint8List? documentBytes,
String? filename, {
required String? title,
int? documentType,
int? correspondent,
List<int>? tags,
DateTime? createdAt,
}) =>
(super.noSuchMethod(
Invocation.method(
#create,
[
documentBytes,
filename,
],
{
#title: title,
#documentType: documentType,
#correspondent: correspondent,
#tags: tags,
#createdAt: createdAt,
},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<_i2.DocumentModel> update(_i2.DocumentModel? doc) =>
(super.noSuchMethod(
Invocation.method(
#update,
[doc],
),
returnValue: _i6.Future<_i2.DocumentModel>.value(_FakeDocumentModel_0(
this,
Invocation.method(
#update,
[doc],
),
)),
returnValueForMissingStub:
_i6.Future<_i2.DocumentModel>.value(_FakeDocumentModel_0(
this,
Invocation.method(
#update,
[doc],
),
)),
) as _i6.Future<_i2.DocumentModel>);
@override
_i6.Future<int> findNextAsn() => (super.noSuchMethod(
Invocation.method(
#findNextAsn,
[],
),
returnValue: _i6.Future<int>.value(0),
returnValueForMissingStub: _i6.Future<int>.value(0),
) as _i6.Future<int>);
@override
_i6.Future<_i3.PagedSearchResult<dynamic>> find(_i8.DocumentFilter? filter) =>
(super.noSuchMethod(
Invocation.method(
#find,
[filter],
),
returnValue: _i6.Future<_i3.PagedSearchResult<dynamic>>.value(
_FakePagedSearchResult_1<dynamic>(
this,
Invocation.method(
#find,
[filter],
),
)),
returnValueForMissingStub:
_i6.Future<_i3.PagedSearchResult<dynamic>>.value(
_FakePagedSearchResult_1<dynamic>(
this,
Invocation.method(
#find,
[filter],
),
)),
) as _i6.Future<_i3.PagedSearchResult<dynamic>>);
@override
_i6.Future<List<_i9.SimilarDocumentModel>> findSimilar(int? docId) =>
(super.noSuchMethod(
Invocation.method(
#findSimilar,
[docId],
),
returnValue: _i6.Future<List<_i9.SimilarDocumentModel>>.value(
<_i9.SimilarDocumentModel>[]),
returnValueForMissingStub:
_i6.Future<List<_i9.SimilarDocumentModel>>.value(
<_i9.SimilarDocumentModel>[]),
) as _i6.Future<List<_i9.SimilarDocumentModel>>);
@override
_i6.Future<int> delete(_i2.DocumentModel? doc) => (super.noSuchMethod(
Invocation.method(
#delete,
[doc],
),
returnValue: _i6.Future<int>.value(0),
returnValueForMissingStub: _i6.Future<int>.value(0),
) as _i6.Future<int>);
@override
_i6.Future<_i4.DocumentMetaData> getMetaData(_i2.DocumentModel? document) =>
(super.noSuchMethod(
Invocation.method(
#getMetaData,
[document],
),
returnValue:
_i6.Future<_i4.DocumentMetaData>.value(_FakeDocumentMetaData_2(
this,
Invocation.method(
#getMetaData,
[document],
),
)),
returnValueForMissingStub:
_i6.Future<_i4.DocumentMetaData>.value(_FakeDocumentMetaData_2(
this,
Invocation.method(
#getMetaData,
[document],
),
)),
) as _i6.Future<_i4.DocumentMetaData>);
@override
_i6.Future<List<int>> bulkDelete(List<_i2.DocumentModel>? models) =>
(super.noSuchMethod(
Invocation.method(
#bulkDelete,
[models],
),
returnValue: _i6.Future<List<int>>.value(<int>[]),
returnValueForMissingStub: _i6.Future<List<int>>.value(<int>[]),
) as _i6.Future<List<int>>);
@override
_i6.Future<_i7.Uint8List> getPreview(int? docId) => (super.noSuchMethod(
Invocation.method(
#getPreview,
[docId],
),
returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)),
returnValueForMissingStub:
_i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)),
) as _i6.Future<_i7.Uint8List>);
@override
String getThumbnailUrl(int? docId) => (super.noSuchMethod(
Invocation.method(
#getThumbnailUrl,
[docId],
),
returnValue: '',
returnValueForMissingStub: '',
) as String);
@override
_i6.Future<_i2.DocumentModel> waitForConsumptionFinished(
String? filename,
String? title,
) =>
(super.noSuchMethod(
Invocation.method(
#waitForConsumptionFinished,
[
filename,
title,
],
),
returnValue: _i6.Future<_i2.DocumentModel>.value(_FakeDocumentModel_0(
this,
Invocation.method(
#waitForConsumptionFinished,
[
filename,
title,
],
),
)),
returnValueForMissingStub:
_i6.Future<_i2.DocumentModel>.value(_FakeDocumentModel_0(
this,
Invocation.method(
#waitForConsumptionFinished,
[
filename,
title,
],
),
)),
) as _i6.Future<_i2.DocumentModel>);
@override
_i6.Future<_i7.Uint8List> download(_i2.DocumentModel? document) =>
(super.noSuchMethod(
Invocation.method(
#download,
[document],
),
returnValue: _i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)),
returnValueForMissingStub:
_i6.Future<_i7.Uint8List>.value(_i7.Uint8List(0)),
) as _i6.Future<_i7.Uint8List>);
@override
_i6.Future<List<String>> autocomplete(
String? query, [
int? limit = 10,
]) =>
(super.noSuchMethod(
Invocation.method(
#autocomplete,
[
query,
limit,
],
),
returnValue: _i6.Future<List<String>>.value(<String>[]),
returnValueForMissingStub: _i6.Future<List<String>>.value(<String>[]),
) as _i6.Future<List<String>>);
}
+256
View File
@@ -0,0 +1,256 @@
import 'package:flutter_paperless_mobile/features/documents/model/document_filter.dart';
import 'package:flutter_paperless_mobile/features/documents/model/filter_rule.model.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/document_type_query.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/query_type.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/sort_order.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/storage_path_query.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/tags_query.dart';
import 'package:flutter_paperless_mobile/features/documents/model/saved_view.model.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/correspondent_query.dart';
import 'package:flutter_paperless_mobile/features/documents/model/query_parameters/sort_field.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('Validate parsing logic from [SavedView] to [DocumentFilter]:', () {
test('Values are correctly parsed if set.', () {
expect(
SavedView.fromJson({
"id": 1,
"name": "test_name",
"show_on_dashboard": false,
"show_in_sidebar": false,
"sort_field": SortField.created.name,
"sort_reverse": true,
"filter_rules": [
{
'rule_type': FilterRule.correspondentRule,
'value': "42",
},
{
'rule_type': FilterRule.documentTypeRule,
'value': "69",
},
{
'rule_type': FilterRule.tagRule,
'value': "1",
},
{
'rule_type': FilterRule.tagRule,
'value': "2",
},
{
'rule_type': FilterRule.tagRule,
'value': "3",
},
{
'rule_type': FilterRule.extendedRule,
'value': "Never gonna give you up",
},
{
'rule_type': FilterRule.storagePathRule,
'value': "14",
},
{
'rule_type': FilterRule.createdBeforeRule,
'value': "2022-10-27",
},
{
'rule_type': FilterRule.createdAfterRule,
'value': "2022-09-27",
},
{
'rule_type': FilterRule.addedBeforeRule,
'value': "2022-09-26",
},
{
'rule_type': FilterRule.addedAfterRule,
'value': "2000-01-01",
}
]
}).toDocumentFilter(),
equals(
DocumentFilter.initial.copyWith(
correspondent: const CorrespondentQuery.fromId(42),
documentType: const DocumentTypeQuery.fromId(69),
storagePath: const StoragePathQuery.fromId(14),
tags: const TagsQuery.fromIds([1, 2, 3]),
createdDateBefore: DateTime.parse("2022-10-27"),
createdDateAfter: DateTime.parse("2022-09-27"),
addedDateBefore: DateTime.parse("2022-09-26"),
addedDateAfter: DateTime.parse("2000-01-01"),
sortField: SortField.created,
sortOrder: SortOrder.ascending,
queryText: "Never gonna give you up",
queryType: QueryType.extended,
),
),
);
});
test('Values are correctly parsed if unset.', () {
expect(
SavedView.fromJson({
"id": 1,
"name": "test_name",
"show_on_dashboard": false,
"show_in_sidebar": false,
"sort_field": SortField.created.name,
"sort_reverse": false,
"filter_rules": [],
}).toDocumentFilter(),
equals(DocumentFilter.initial),
);
});
test('Values are correctly parsed if not assigned.', () {
expect(
SavedView.fromJson({
"id": 1,
"name": "test_name",
"show_on_dashboard": false,
"show_in_sidebar": false,
"sort_field": SortField.created.name,
"sort_reverse": false,
"filter_rules": [
{
'rule_type': FilterRule.correspondentRule,
'value': null,
},
{
'rule_type': FilterRule.documentTypeRule,
'value': null,
},
{
'rule_type': FilterRule.tagRule,
'value': null,
},
{
'rule_type': FilterRule.storagePathRule,
'value': null,
},
],
}).toDocumentFilter(),
equals(DocumentFilter.initial.copyWith(
correspondent: const CorrespondentQuery.notAssigned(),
documentType: const DocumentTypeQuery.notAssigned(),
storagePath: const StoragePathQuery.notAssigned(),
tags: const TagsQuery.notAssigned(),
)),
);
});
});
group('Validate parsing logic from [DocumentFilter] to [SavedView]:', () {
test('Values are correctly parsed if set.', () {
expect(
SavedView.fromDocumentFilter(
DocumentFilter(
correspondent: const CorrespondentQuery.fromId(1),
documentType: const DocumentTypeQuery.fromId(2),
storagePath: const StoragePathQuery.fromId(3),
tags: const TagsQuery.fromIds([4, 5, 6]),
sortField: SortField.added,
sortOrder: SortOrder.ascending,
addedDateAfter: DateTime.parse("2020-01-01"),
addedDateBefore: DateTime.parse("2020-03-01"),
createdDateAfter: DateTime.parse("2020-02-01"),
createdDateBefore: DateTime.parse("2020-04-01"),
queryText: "Never gonna let you down",
queryType: QueryType.title,
),
name: "test_name",
showInSidebar: false,
showOnDashboard: false,
),
equals(
SavedView(
name: "test_name",
showOnDashboard: false,
showInSidebar: false,
sortField: SortField.added,
sortReverse: true,
filterRules: [
FilterRule(FilterRule.correspondentRule, "1"),
FilterRule(FilterRule.documentTypeRule, "2"),
FilterRule(FilterRule.storagePathRule, "3"),
FilterRule(FilterRule.tagRule, "4"),
FilterRule(FilterRule.tagRule, "5"),
FilterRule(FilterRule.tagRule, "6"),
FilterRule(FilterRule.addedAfterRule, "2020-01-01"),
FilterRule(FilterRule.addedBeforeRule, "2020-03-01"),
FilterRule(FilterRule.createdAfterRule, "2020-02-01"),
FilterRule(FilterRule.createdBeforeRule, "2020-04-01"),
FilterRule(FilterRule.titleRule, "Never gonna let you down"),
],
),
),
);
});
test('Values are correctly parsed if unset.', () {
expect(
SavedView.fromDocumentFilter(
const DocumentFilter(
correspondent: CorrespondentQuery.unset(),
documentType: DocumentTypeQuery.unset(),
storagePath: StoragePathQuery.unset(),
tags: TagsQuery.unset(),
sortField: SortField.created,
sortOrder: SortOrder.descending,
addedDateAfter: null,
addedDateBefore: null,
createdDateAfter: null,
createdDateBefore: null,
queryText: null,
),
name: "test_name",
showInSidebar: false,
showOnDashboard: false,
),
equals(
SavedView(
name: "test_name",
showOnDashboard: false,
showInSidebar: false,
sortField: SortField.created,
sortReverse: false,
filterRules: [],
),
),
);
});
test('Values are correctly parsed if not assigned.', () {
expect(
SavedView.fromDocumentFilter(
const DocumentFilter(
correspondent: CorrespondentQuery.notAssigned(),
documentType: DocumentTypeQuery.notAssigned(),
storagePath: StoragePathQuery.notAssigned(),
tags: TagsQuery.notAssigned(),
sortField: SortField.created,
sortOrder: SortOrder.descending,
),
name: "test_name",
showInSidebar: false,
showOnDashboard: false,
),
equals(
SavedView(
name: "test_name",
showOnDashboard: false,
showInSidebar: false,
sortField: SortField.created,
sortReverse: false,
filterRules: [
FilterRule(FilterRule.correspondentRule, null),
FilterRule(FilterRule.documentTypeRule, null),
FilterRule(FilterRule.storagePathRule, null),
FilterRule(FilterRule.tagRule, null),
],
),
),
);
});
});
}
+12
View File
@@ -0,0 +1,12 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Login validation error fields test', (WidgetTester tester) async {});
}