Skip to content

Add comprehensive error handling and test coverage for analyze#47

Merged
YusukeHirao merged 4 commits intomainfrom
claude/fix-analyze-empty-results-7ieOv
Mar 5, 2026
Merged

Add comprehensive error handling and test coverage for analyze#47
YusukeHirao merged 4 commits intomainfrom
claude/fix-analyze-empty-results-7ieOv

Conversation

@YusukeHirao
Copy link
Copy Markdown
Member

@YusukeHirao YusukeHirao commented Mar 5, 2026

Summary

This PR adds robust error handling to the analyze() method and comprehensive test coverage for the analyze pipeline, including all analyze plugins. Error handling now gracefully continues processing when individual pages or plugins fail, emits error events for visibility, and warns when plugins produce no data.

closes: #35

Key Changes

Core Error Handling (nitpicker.ts)

  • Wrapped page analysis loop in try-catch to handle per-page failures without stopping the entire plugin
  • Added error event emission when worker tasks fail with plugin name and URL context
  • Added warning when a plugin produces zero page data across all pages
  • Track error counts per plugin to provide context in warning messages
  • Errors are now caught and reported rather than crashing the analysis

Worker Error Propagation (worker.ts, page-analysis-worker.ts)

  • Worker now catches fatal errors and sends them back to parent thread with error message
  • page-analysis-worker.ts throws errors with plugin name prefix instead of logging to console
  • Errors propagate through runInWorker() to be handled by the main analyze loop

Test Coverage

  • Added 326 lines of comprehensive tests for analyze() method covering:
    • Valid results saved to report
    • Continuation when single worker task throws
    • Error event emission on worker failure
    • Warning when all page results are empty
    • Continuation when eachUrl plugin throws
    • Preservation of results from other plugins when one fails
    • Graceful handling of getHtml() failures
    • Skipping pages with no HTML snapshot
  • Added full test suites for all analyze plugins:
    • analyze-textlint: 216 lines covering linting, severity conversion, custom rules
    • analyze-search: 201 lines covering keyword/selector search, scope restriction
    • analyze-main-contents: 178 lines covering content detection and counting
    • analyze-markuplint: 174 lines covering HTML validation and URL normalization

Documentation

  • Added CONTRIBUTING.md with development setup, workflow, coding conventions, and external dependencies
  • Updated ARCHITECTURE.md with external dependency reference table and worker thread error handling details

CI/CD

  • Updated GitHub Actions workflow to upload build artifacts for test job consumption

Implementation Details

  • Error handling uses bounded Promise pool pattern to maintain concurrency while catching individual failures
  • Plugin-level errors don't prevent other plugins from processing the same pages
  • Page-level errors don't prevent other pages from being processed by the same plugin
  • All errors are emitted as events for logging/monitoring rather than thrown
  • Tests use comprehensive mocking of JSDOM, worker threads, and external linters

https://claude.ai/code/session_01GGS8WVVNwxG2ueyEdyVUYW

@YusukeHirao YusukeHirao force-pushed the claude/fix-analyze-empty-results-7ieOv branch from 6d26a62 to b8ac0b8 Compare March 5, 2026 12:43
claude added 4 commits March 5, 2026 12:48
The bounded Promise pool in Nitpicker.analyze() did not catch individual
task errors. When runInWorker() rejected (e.g., worker crash, OOM, plugin
import failure), the rejection propagated to Promise.race/Promise.all,
crashing the entire analyze flow before saving any results to the archive.

Changes:
- Wrap each page analysis task in try-catch so a single page failure
  does not abort the entire plugin run
- Emit 'error' events for individual page failures with URL context
- Emit a warning when a plugin produces no page data at all
- Add try-catch in worker.ts to send a graceful 'finish' message
  with null result when runner() throws, instead of crashing
- Add unit tests covering error resilience and empty-result warnings

Closes #35

https://claude.ai/code/session_01GGS8WVVNwxG2ueyEdyVUYW
- Add try-catch to Phase 2 (eachUrl) so a single plugin failure does
  not abort remaining URL checks or prevent report saving
- Propagate worker error field in run-in-worker.ts: when worker.ts
  sends { error }, reject the promise instead of silently resolving null
- Re-throw plugin errors from page-analysis-worker.ts instead of
  swallowing them, so they propagate through worker -> main thread ->
  error event chain for proper visibility
- Replace allViolations.push(...spread) with for-of loop to avoid
  potential stack overflow with very large violation arrays
- Strengthen test: verify exact error event count in "emits error" test
- Add tests: eachUrl error resilience, multi-plugin partial failure,
  getHtml() rejection handling

https://claude.ai/code/session_01GGS8WVVNwxG2ueyEdyVUYW
- Add unit tests for 4 untested analyze plugins:
  - analyze-main-contents (6 tests): main detection, headings, images, tables
  - analyze-markuplint (7 tests): violations, URL naming, error handling
  - analyze-search (9 tests): keywords, selectors, scope, headers
  - analyze-textlint (6 tests): violations, severity mapping, rule merging
- Create CONTRIBUTING.md with dev setup, workflow, and coding conventions
- Create .env.example documenting Google OAuth2 credential setup
- Add external dependency reference section to ARCHITECTURE.md
  with @d-zero/* package versions, usage map, and update notes
- Optimize CI: share build artifacts between build and test jobs
  via actions/upload-artifact to eliminate redundant rebuild

Test coverage: 79 → 83 files, 462 → 490 tests

https://claude.ai/code/session_01GGS8WVVNwxG2ueyEdyVUYW
- Fix duplicate section 9 numbering (External Dependencies → section 13)
- Complete dependency graph (add analyze-* → core and @d-zero/dealer edges)
- Fix filesystem file count (14 → 16)
- Remove specific version numbers from external deps table per project rules
- Add missing @d-zero/fs and @d-zero/readtext to usage map

https://claude.ai/code/session_01GGS8WVVNwxG2ueyEdyVUYW
@YusukeHirao YusukeHirao force-pushed the claude/fix-analyze-empty-results-7ieOv branch from b8ac0b8 to 87b4c41 Compare March 5, 2026 12:49
@YusukeHirao YusukeHirao merged commit 929c4ef into main Mar 5, 2026
3 checks passed
@YusukeHirao YusukeHirao deleted the claude/fix-analyze-empty-results-7ieOv branch March 5, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug(core): analyze 結果がサイレントに空になる

2 participants