Skip to content

Commit 449f447

Browse files
committed
Add widget tests for library components and update CI workflow to generate code coverage reports.
1 parent 853958f commit 449f447

11 files changed

Lines changed: 1612 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,12 @@ jobs:
4747
- name: Analyze code
4848
run: dart analyze
4949

50-
- name: Run tests
51-
run: flutter test
50+
- name: Run tests with coverage
51+
run: flutter test --coverage
52+
53+
- name: Upload coverage to Codecov
54+
uses: codecov/codecov-action@v4
55+
with:
56+
files: client/coverage/lcov.info
57+
flags: client
58+
token: ${{ secrets.CODECOV_TOKEN }}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<a href="https://eoic.github.io/Papyrus/"><img src="https://img.shields.io/badge/Documentation-blue?logo=gitbook&logoColor=white" alt="Documentation"/></a>
99
<a href="https://trello.com/invite/b/681367b2ba91db4e40b0cfea/ATTI5156837607437467bd3d646f933528054D126F02/papyrus"><img src="https://img.shields.io/badge/Trello-Board-blue?logo=trello&logoColor=white" alt="Trello Board"/></a>
1010
<a href="https://www.figma.com/design/nnL41KQvrlVU4ecF8mtB07/Papyrus"><img src="https://img.shields.io/badge/Figma-Prototype-orange?logo=figma&logoColor=white" alt="Figma Prototype"/></a>
11+
<a href="https://codecov.io/gh/Eoic/Papyrus"><img src="https://codecov.io/gh/Eoic/Papyrus/branch/master/graph/badge.svg" alt="Coverage"/></a>
1112
<img src="https://img.shields.io/badge/License-AGPL--3.0-blue" alt="License"/>
1213
</p>
1314
</div>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:papyrus/data/data_store.dart';
3+
import 'package:papyrus/models/book.dart';
4+
import 'package:papyrus/models/shelf.dart';
5+
import 'package:papyrus/models/tag.dart';
6+
import 'package:papyrus/providers/library_provider.dart';
7+
import 'package:provider/provider.dart';
8+
9+
/// Creates a [MaterialApp] wrapper with required providers for widget testing.
10+
Widget createTestApp({
11+
required Widget child,
12+
LibraryProvider? libraryProvider,
13+
DataStore? dataStore,
14+
Size screenSize = const Size(400, 800),
15+
}) {
16+
return MultiProvider(
17+
providers: [
18+
ChangeNotifierProvider<LibraryProvider>.value(
19+
value: libraryProvider ?? LibraryProvider(),
20+
),
21+
ChangeNotifierProvider<DataStore>.value(value: dataStore ?? DataStore()),
22+
],
23+
child: MaterialApp(
24+
home: MediaQuery(
25+
data: MediaQueryData(size: screenSize),
26+
child: Scaffold(body: child),
27+
),
28+
),
29+
);
30+
}
31+
32+
/// Creates a [MaterialApp] wrapper with a custom builder for full-page tests.
33+
Widget createTestPage({
34+
required Widget page,
35+
LibraryProvider? libraryProvider,
36+
DataStore? dataStore,
37+
Size screenSize = const Size(400, 800),
38+
}) {
39+
return MultiProvider(
40+
providers: [
41+
ChangeNotifierProvider<LibraryProvider>.value(
42+
value: libraryProvider ?? LibraryProvider(),
43+
),
44+
ChangeNotifierProvider<DataStore>.value(value: dataStore ?? DataStore()),
45+
],
46+
child: MaterialApp(
47+
home: MediaQuery(
48+
data: MediaQueryData(size: screenSize),
49+
child: page,
50+
),
51+
),
52+
);
53+
}
54+
55+
/// Creates test books with various states for filtering tests.
56+
List<Book> createTestBooks() {
57+
final now = DateTime.now();
58+
return [
59+
Book(
60+
id: 'book-1',
61+
title: 'The Hobbit',
62+
author: 'J.R.R. Tolkien',
63+
readingStatus: ReadingStatus.inProgress,
64+
currentPosition: 0.5,
65+
isFavorite: true,
66+
fileFormat: BookFormat.epub,
67+
addedAt: now,
68+
),
69+
Book(
70+
id: 'book-2',
71+
title: 'Dune',
72+
author: 'Frank Herbert',
73+
readingStatus: ReadingStatus.completed,
74+
currentPosition: 1.0,
75+
isFavorite: false,
76+
fileFormat: BookFormat.pdf,
77+
addedAt: now,
78+
),
79+
Book(
80+
id: 'book-3',
81+
title: '1984',
82+
author: 'George Orwell',
83+
readingStatus: ReadingStatus.notStarted,
84+
currentPosition: 0.0,
85+
isFavorite: false,
86+
fileFormat: BookFormat.mobi,
87+
addedAt: now,
88+
),
89+
Book(
90+
id: 'book-4',
91+
title: 'Foundation',
92+
author: 'Isaac Asimov',
93+
readingStatus: ReadingStatus.notStarted,
94+
currentPosition: 0.0,
95+
isFavorite: true,
96+
isPhysical: true,
97+
addedAt: now,
98+
),
99+
Book(
100+
id: 'book-5',
101+
title: 'Neuromancer',
102+
author: 'William Gibson',
103+
readingStatus: ReadingStatus.inProgress,
104+
currentPosition: 0.25,
105+
isFavorite: false,
106+
fileFormat: BookFormat.epub,
107+
addedAt: now,
108+
),
109+
];
110+
}
111+
112+
/// Creates a [DataStore] pre-loaded with test data.
113+
DataStore createTestDataStore({
114+
List<Book>? books,
115+
List<Shelf>? shelves,
116+
List<Tag>? tags,
117+
}) {
118+
final now = DateTime.now();
119+
final store = DataStore();
120+
store.loadData(
121+
books: books ?? createTestBooks(),
122+
shelves:
123+
shelves ??
124+
[
125+
Shelf(id: 'shelf-1', name: 'Fiction', createdAt: now, updatedAt: now),
126+
Shelf(
127+
id: 'shelf-2',
128+
name: 'Science Fiction',
129+
createdAt: now,
130+
updatedAt: now,
131+
),
132+
],
133+
tags:
134+
tags ??
135+
[
136+
Tag(
137+
id: 'tag-1',
138+
name: 'Fantasy',
139+
colorHex: '#4CAF50',
140+
createdAt: now,
141+
),
142+
Tag(
143+
id: 'tag-2',
144+
name: 'Classic',
145+
colorHex: '#2196F3',
146+
createdAt: now,
147+
),
148+
],
149+
);
150+
return store;
151+
}

0 commit comments

Comments
 (0)