Skip to content

Commit dc64266

Browse files
Copilotsantoshvandarigithub-actions[bot]
authored
Add comprehensive test suite (43 tests) with fixtures and documentation (#22)
* Initial plan * Add comprehensive test suite for docx_viewer package Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Add test documentation and update README with testing information Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Add comprehensive test implementation summary Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Add post-merge checklist for test suite integration Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Fix code review feedback - remove unused variable Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Remove unused import from file_io_stub_test.dart Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * style: auto-format code with dart format [skip ci] * Remove unnecessary files and check icons as per review feedback Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Remove emojis from run_tests.sh output * Fix analyzer warnings - remove unnecessary non-null assertions Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * Fix test failures - handle loading state in error callback and fix numbered list detection Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> * style: auto-format code with dart format [skip ci] --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: santoshvandari <63558580+santoshvandari@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 3a5b1d7 commit dc64266

12 files changed

Lines changed: 1105 additions & 19 deletions

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,38 @@ All three methods work:
201201

202202
If the DOCX file path is empty, the file type is unsupported, or the file doesn't exist, an error message will be displayed. If you provide an `onError` callback, it will be invoked with the error.
203203

204+
## Testing
205+
206+
This package includes comprehensive test coverage to ensure reliability across all platforms. The test suite covers:
207+
208+
- Text extraction from DOCX files (various formats, edge cases)
209+
- Widget functionality (loading states, error handling, display)
210+
- Platform-specific file I/O implementations
211+
- Error handling and edge cases
212+
213+
### Running Tests
214+
215+
```bash
216+
# Run all tests
217+
flutter test
218+
219+
# Run tests with coverage
220+
flutter test --coverage
221+
222+
# Use the provided test runner script
223+
./test/run_tests.sh
224+
```
225+
226+
### Continuous Integration
227+
228+
Tests are automatically run on every pull request through GitHub Actions. The CI pipeline:
229+
- Runs static analysis and formatting checks
230+
- Executes all tests with coverage reporting
231+
- Posts coverage reports as PR comments
232+
- Ensures code quality standards are met
233+
234+
For more details about the test suite, see [test/README.md](test/README.md).
235+
204236
## Contributing
205237
We welcome contributions! If you'd like to contribute to this Flutter Package Project, please check out our [Contribution Guidelines](Contribution.md).
206238

lib/src/docx_view.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,15 @@ class _DocxViewState extends State<DocxView> {
194194

195195
/// Handles errors by calling the [onError] callback if provided, or displaying the error message.
196196
void _handleError(Exception error) {
197+
setState(() {
198+
isLoading = false;
199+
});
200+
197201
if (widget.onError != null) {
198202
widget.onError!(error);
199203
} else {
200204
setState(() {
201205
fileContent = error.toString();
202-
isLoading = false;
203206
});
204207
}
205208
}

lib/src/extract_text_from_docx.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ String extractTextFromDocxBytes(Uint8List bytes) {
4343
paragraph.findAllElements('w:t').map((node) => node.innerText).join();
4444

4545
// Check for numbering information in the paragraph
46-
final numIdNode = paragraph.findElements('w:numId').firstOrNull;
46+
final numIdNode = paragraph.findAllElements('w:numId').firstOrNull;
4747
final numId = numIdNode?.getAttribute('w:val');
4848

4949
// Manage numbering: increment or reset based on numId changes

test/README.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Test Suite Documentation
2+
3+
This directory contains comprehensive test coverage for the `docx_viewer` package.
4+
5+
## Test Structure
6+
7+
```
8+
test/
9+
├── docx_viewer_test.dart # Main test entry point
10+
├── fixtures/
11+
│ └── test_docx_generator.dart # Helper to generate test DOCX files
12+
├── src/
13+
│ ├── docx_view_test.dart # Widget tests for DocxView
14+
│ ├── extract_text_from_docx_test.dart # Tests for text extraction
15+
│ ├── file_io_stub_test.dart # Tests for stub implementation
16+
│ └── file_io_web_test.dart # Tests for web implementation
17+
└── utils/
18+
└── support_type_test.dart # Tests for utility classes
19+
```
20+
21+
## Test Coverage
22+
23+
### 1. Text Extraction Tests (`src/extract_text_from_docx_test.dart`)
24+
- Extract text from simple DOCX files
25+
- Extract text from DOCX with multiple paragraphs
26+
- Handle empty DOCX documents
27+
- Extract and number items from DOCX with numbering
28+
- Handle special characters and unicode
29+
- Handle invalid ZIP/DOCX data
30+
- Handle empty paragraphs and whitespace
31+
- Handle long text content
32+
- Test FirstOrNullExtension utility
33+
34+
### 2. DocxView Widget Tests (`src/docx_view_test.dart`)
35+
- Display loading indicator during content load
36+
- Display content after loading with bytes parameter
37+
- Apply custom font size
38+
- Use default font size when not specified
39+
- Display multiple paragraphs with newlines
40+
- Handle empty documents
41+
- Call onError callback when no input provided
42+
- Display error messages without callback
43+
- Validate error when both filePath and bytes provided
44+
- Handle invalid bytes gracefully
45+
- Render content in scrollable view
46+
- Handle numbered lists
47+
- Apply correct padding
48+
49+
### 3. Platform-Specific File I/O Tests
50+
- Stub implementation tests (`src/file_io_stub_test.dart`)
51+
- Web implementation tests (`src/file_io_web_test.dart`)
52+
- Verify proper error messages for unsupported operations
53+
54+
### 4. Utility Tests (`utils/support_type_test.dart`)
55+
- Validate Supporttype constants
56+
57+
## Running Tests
58+
59+
### Run All Tests
60+
```bash
61+
flutter test
62+
```
63+
64+
### Run Tests with Coverage
65+
```bash
66+
flutter test --coverage
67+
```
68+
69+
### Run Specific Test File
70+
```bash
71+
flutter test test/src/docx_view_test.dart
72+
```
73+
74+
### View Coverage Report
75+
After running tests with coverage, you can generate an HTML report:
76+
77+
```bash
78+
# Install lcov (Ubuntu/Debian)
79+
sudo apt-get install lcov
80+
81+
# Generate HTML report
82+
genhtml coverage/lcov.info -o coverage/html
83+
84+
# Open in browser
85+
open coverage/html/index.html
86+
```
87+
88+
## Test Fixtures
89+
90+
The `fixtures/test_docx_generator.dart` file provides helper methods to generate test DOCX files:
91+
92+
- `createSimpleDocx(String text)` - Creates a simple DOCX with given text
93+
- `createDocxWithNumbering(List<String> items)` - Creates DOCX with numbered list
94+
- `createEmptyDocx()` - Creates an empty DOCX file
95+
- `createDocxWithMultipleParagraphs(List<String> paragraphs)` - Creates DOCX with multiple paragraphs
96+
97+
These helpers create proper DOCX files (ZIP archives) with the correct XML structure for testing.
98+
99+
## Continuous Integration
100+
101+
Tests are automatically run on every pull request through GitHub Actions (`.github/workflows/ci.yml`):
102+
103+
1. **Analyze Job**: Runs static analysis and formatting checks
104+
2. **Test Job**: Runs all tests with coverage
105+
- Generates coverage report
106+
- Posts coverage summary as PR comment
107+
- Uploads coverage artifacts
108+
109+
The CI workflow:
110+
- Runs on pull requests to `main` and `dev` branches
111+
- Runs on push to `main` and `dev` branches
112+
- Generates test coverage reports
113+
- Comments on PRs with coverage information
114+
- Provides coverage badges
115+
116+
## Adding New Tests
117+
118+
When adding new tests:
119+
120+
1. Create test files in appropriate directories (`src/`, `utils/`, etc.)
121+
2. Follow the existing test structure and naming conventions
122+
3. Use descriptive test names that explain what is being tested
123+
4. Include arrange-act-assert comments in tests for clarity
124+
5. Import the test file in `docx_viewer_test.dart` to include in the main test suite
125+
6. Run tests locally before committing
126+
127+
Example:
128+
```dart
129+
import 'package:flutter_test/flutter_test.dart';
130+
131+
void main() {
132+
group('FeatureName', () {
133+
test('should do something specific', () {
134+
// Arrange
135+
final input = 'test';
136+
137+
// Act
138+
final result = functionUnderTest(input);
139+
140+
// Assert
141+
expect(result, equals('expected'));
142+
});
143+
});
144+
}
145+
```
146+
147+
## Test Best Practices
148+
149+
1. **Isolation**: Each test should be independent and not rely on other tests
150+
2. **Clarity**: Use descriptive test names that explain the scenario
151+
3. **Coverage**: Aim for high coverage but focus on meaningful tests
152+
4. **Edge Cases**: Test boundary conditions, error cases, and edge cases
153+
5. **Maintainability**: Keep tests simple and maintainable
154+
6. **Performance**: Tests should run quickly to support rapid development
155+
156+
## Coverage Goals
157+
158+
The package aims for:
159+
- **Minimum**: 80% code coverage
160+
- **Target**: 90%+ code coverage
161+
- **Focus**: All critical paths and error handling must be tested
162+
163+
Current coverage is tracked automatically in CI and reported on pull requests.

test/docx_viewer_test.dart

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
import 'package:flutter/material.dart';
21
import 'package:flutter_test/flutter_test.dart';
32

4-
import 'package:docx_viewer/docx_viewer.dart';
3+
// Import all test suites
4+
import 'src/extract_text_from_docx_test.dart' as extract_text_tests;
5+
import 'src/docx_view_test.dart' as docx_view_tests;
6+
import 'src/file_io_stub_test.dart' as file_io_stub_tests;
7+
import 'src/file_io_web_test.dart' as file_io_web_tests;
8+
import 'utils/support_type_test.dart' as support_type_tests;
59

10+
/// Main test file that runs all test suites for the docx_viewer package
11+
///
12+
/// This ensures comprehensive test coverage across all components:
13+
/// - Text extraction from DOCX files
14+
/// - DocxView widget functionality
15+
/// - Platform-specific file I/O implementations
16+
/// - Utility classes
617
void main() {
7-
test('adds one to input values', () {
8-
DocxView(
9-
filePath: 'docs/sample.docx',
10-
onError: (error) {
11-
debugPrint(error.toString());
12-
},
13-
);
14-
15-
DocxView(
16-
filePath: 'docs/sample.pdf',
17-
onError: (error) {
18-
debugPrint(error.toString());
19-
},
20-
);
21-
});
18+
group('Extract Text from DOCX Tests', extract_text_tests.main);
19+
group('DocxView Widget Tests', docx_view_tests.main);
20+
group('FileIO Stub Tests', file_io_stub_tests.main);
21+
group('FileIO Web Tests', file_io_web_tests.main);
22+
group('Support Type Tests', support_type_tests.main);
2223
}

0 commit comments

Comments
 (0)