groundswell 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +26 -9
- package/dist/cache/cache-key.d.ts +86 -0
- package/dist/cache/cache-key.d.ts.map +1 -0
- package/dist/cache/cache-key.js +204 -0
- package/dist/cache/cache-key.js.map +1 -0
- package/dist/cache/cache.d.ts +104 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +179 -0
- package/dist/cache/cache.js.map +1 -0
- package/{src/cache/index.ts → dist/cache/index.d.ts} +1 -1
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +6 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/core/agent.d.ts +203 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +833 -0
- package/dist/core/agent.js.map +1 -0
- package/{src/core/context.ts → dist/core/context.d.ts} +16 -67
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +80 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/event-tree.d.ts +72 -0
- package/dist/core/event-tree.d.ts.map +1 -0
- package/dist/core/event-tree.js +211 -0
- package/dist/core/event-tree.js.map +1 -0
- package/{src/core/factory.ts → dist/core/factory.d.ts} +6 -27
- package/dist/core/factory.d.ts.map +1 -0
- package/dist/core/factory.js +110 -0
- package/dist/core/factory.js.map +1 -0
- package/{src/core/index.ts → dist/core/index.d.ts} +2 -10
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +50 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +91 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mcp-handler.d.ts +127 -0
- package/dist/core/mcp-handler.d.ts.map +1 -0
- package/dist/core/mcp-handler.js +323 -0
- package/dist/core/mcp-handler.js.map +1 -0
- package/dist/core/prompt.d.ts +80 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +120 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/workflow-context.d.ts +61 -0
- package/dist/core/workflow-context.d.ts.map +1 -0
- package/dist/core/workflow-context.js +358 -0
- package/dist/core/workflow-context.js.map +1 -0
- package/dist/core/workflow.d.ts +543 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +986 -0
- package/dist/core/workflow.js.map +1 -0
- package/dist/debugger/event-replayer.d.ts +422 -0
- package/dist/debugger/event-replayer.d.ts.map +1 -0
- package/dist/debugger/event-replayer.js +639 -0
- package/dist/debugger/event-replayer.js.map +1 -0
- package/dist/debugger/index.d.ts +2 -0
- package/dist/debugger/index.d.ts.map +1 -0
- package/{src/debugger/index.ts → dist/debugger/index.js} +1 -0
- package/dist/debugger/index.js.map +1 -0
- package/dist/debugger/tree-debugger.d.ts +240 -0
- package/dist/debugger/tree-debugger.d.ts.map +1 -0
- package/dist/debugger/tree-debugger.js +620 -0
- package/dist/debugger/tree-debugger.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/{src/decorators/index.ts → dist/decorators/index.js} +1 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/observed-state.d.ts +32 -0
- package/dist/decorators/observed-state.d.ts.map +1 -0
- package/dist/decorators/observed-state.js +79 -0
- package/dist/decorators/observed-state.js.map +1 -0
- package/dist/decorators/step.d.ts +15 -0
- package/dist/decorators/step.d.ts.map +1 -0
- package/dist/decorators/step.js +192 -0
- package/dist/decorators/step.js.map +1 -0
- package/dist/decorators/task.d.ts +50 -0
- package/dist/decorators/task.d.ts.map +1 -0
- package/dist/decorators/task.js +118 -0
- package/dist/decorators/task.js.map +1 -0
- package/dist/examples/index.d.ts +3 -0
- package/dist/examples/index.d.ts.map +1 -0
- package/{src/examples/index.ts → dist/examples/index.js} +1 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/examples/tdd-orchestrator.d.ts +15 -0
- package/dist/examples/tdd-orchestrator.d.ts.map +1 -0
- package/dist/examples/tdd-orchestrator.js +121 -0
- package/dist/examples/tdd-orchestrator.js.map +1 -0
- package/dist/examples/test-cycle-workflow.d.ts +14 -0
- package/dist/examples/test-cycle-workflow.d.ts.map +1 -0
- package/dist/examples/test-cycle-workflow.js +116 -0
- package/dist/examples/test-cycle-workflow.js.map +1 -0
- package/dist/harnesses/claude-code-harness.d.ts +391 -0
- package/dist/harnesses/claude-code-harness.d.ts.map +1 -0
- package/dist/harnesses/claude-code-harness.js +1076 -0
- package/dist/harnesses/claude-code-harness.js.map +1 -0
- package/dist/harnesses/harness-registry.d.ts +440 -0
- package/dist/harnesses/harness-registry.d.ts.map +1 -0
- package/dist/harnesses/harness-registry.js +543 -0
- package/dist/harnesses/harness-registry.js.map +1 -0
- package/dist/harnesses/index.d.ts +12 -0
- package/dist/harnesses/index.d.ts.map +1 -0
- package/dist/harnesses/index.js +11 -0
- package/dist/harnesses/index.js.map +1 -0
- package/dist/harnesses/pi-harness.d.ts +219 -0
- package/dist/harnesses/pi-harness.d.ts.map +1 -0
- package/dist/harnesses/pi-harness.js +676 -0
- package/dist/harnesses/pi-harness.js.map +1 -0
- package/dist/harnesses/pi-schema-converter.d.ts +24 -0
- package/dist/harnesses/pi-schema-converter.d.ts.map +1 -0
- package/dist/harnesses/pi-schema-converter.js +81 -0
- package/dist/harnesses/pi-schema-converter.js.map +1 -0
- package/dist/harnesses/register-defaults.d.ts +24 -0
- package/dist/harnesses/register-defaults.d.ts.map +1 -0
- package/dist/harnesses/register-defaults.js +40 -0
- package/dist/harnesses/register-defaults.js.map +1 -0
- package/dist/harnesses/session-store.d.ts +201 -0
- package/dist/harnesses/session-store.d.ts.map +1 -0
- package/dist/harnesses/session-store.js +254 -0
- package/dist/harnesses/session-store.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/reflection/index.d.ts +5 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/{src/reflection/index.ts → dist/reflection/index.js} +1 -1
- package/dist/reflection/index.js.map +1 -0
- package/dist/reflection/reflection.d.ts +84 -0
- package/dist/reflection/reflection.d.ts.map +1 -0
- package/dist/reflection/reflection.js +344 -0
- package/dist/reflection/reflection.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/introspection.d.ts +165 -0
- package/dist/tools/introspection.d.ts.map +1 -0
- package/dist/tools/introspection.js +324 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/types/agent.d.ts +1317 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +423 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/decorators.d.ts +40 -0
- package/dist/types/decorators.d.ts.map +1 -0
- package/dist/types/decorators.js +2 -0
- package/dist/types/decorators.js.map +1 -0
- package/dist/types/error-strategy.d.ts +13 -0
- package/dist/types/error-strategy.d.ts.map +1 -0
- package/dist/types/error-strategy.js +2 -0
- package/dist/types/error-strategy.js.map +1 -0
- package/dist/types/error.d.ts +20 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/error.js +2 -0
- package/dist/types/error.js.map +1 -0
- package/dist/types/events.d.ts +113 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/harnesses.d.ts +474 -0
- package/dist/types/harnesses.d.ts.map +1 -0
- package/dist/types/harnesses.js +2 -0
- package/dist/types/harnesses.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/logging.d.ts +24 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/logging.js +2 -0
- package/dist/types/logging.js.map +1 -0
- package/dist/types/observer.d.ts +18 -0
- package/dist/types/observer.d.ts.map +1 -0
- package/dist/types/observer.js +2 -0
- package/dist/types/observer.js.map +1 -0
- package/dist/types/prompt.d.ts +31 -0
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/types/prompt.js +6 -0
- package/dist/types/prompt.js.map +1 -0
- package/dist/types/providers.d.ts +691 -0
- package/dist/types/providers.d.ts.map +1 -0
- package/dist/types/providers.js +14 -0
- package/dist/types/providers.js.map +1 -0
- package/dist/types/reflection.d.ts +96 -0
- package/dist/types/reflection.d.ts.map +1 -0
- package/dist/types/reflection.js +24 -0
- package/dist/types/reflection.js.map +1 -0
- package/dist/types/restart.d.ts +132 -0
- package/dist/types/restart.d.ts.map +1 -0
- package/dist/types/restart.js +2 -0
- package/dist/types/restart.js.map +1 -0
- package/dist/types/sdk-primitives.d.ts +118 -0
- package/dist/types/sdk-primitives.d.ts.map +1 -0
- package/dist/types/sdk-primitives.js +6 -0
- package/dist/types/sdk-primitives.js.map +1 -0
- package/{src/types/snapshot.ts → dist/types/snapshot.d.ts} +5 -5
- package/dist/types/snapshot.d.ts.map +1 -0
- package/dist/types/snapshot.js +2 -0
- package/dist/types/snapshot.js.map +1 -0
- package/dist/types/streaming.d.ts +194 -0
- package/dist/types/streaming.d.ts.map +1 -0
- package/dist/types/streaming.js +67 -0
- package/dist/types/streaming.js.map +1 -0
- package/dist/types/workflow-context.d.ts +275 -0
- package/dist/types/workflow-context.d.ts.map +1 -0
- package/dist/types/workflow-context.js +8 -0
- package/dist/types/workflow-context.js.map +1 -0
- package/dist/types/workflow.d.ts +30 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +2 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/agent-validation.d.ts +88 -0
- package/dist/utils/agent-validation.d.ts.map +1 -0
- package/dist/utils/agent-validation.js +87 -0
- package/dist/utils/agent-validation.js.map +1 -0
- package/dist/utils/delay.d.ts +7 -0
- package/dist/utils/delay.d.ts.map +1 -0
- package/dist/utils/delay.js +9 -0
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/harness-config.d.ts +180 -0
- package/dist/utils/harness-config.d.ts.map +1 -0
- package/dist/utils/harness-config.js +311 -0
- package/dist/utils/harness-config.js.map +1 -0
- package/dist/utils/id.d.ts +6 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +12 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/model-spec.d.ts +110 -0
- package/dist/utils/model-spec.d.ts.map +1 -0
- package/dist/utils/model-spec.js +149 -0
- package/dist/utils/model-spec.js.map +1 -0
- package/dist/utils/observable.d.ts +54 -0
- package/dist/utils/observable.d.ts.map +1 -0
- package/dist/utils/observable.js +82 -0
- package/dist/utils/observable.js.map +1 -0
- package/dist/utils/provider-config.d.ts +10 -0
- package/dist/utils/provider-config.d.ts.map +1 -0
- package/dist/utils/provider-config.js +10 -0
- package/dist/utils/provider-config.js.map +1 -0
- package/dist/utils/restart-analysis.d.ts +202 -0
- package/dist/utils/restart-analysis.d.ts.map +1 -0
- package/dist/utils/restart-analysis.js +426 -0
- package/dist/utils/restart-analysis.js.map +1 -0
- package/dist/utils/session-serialization.d.ts +118 -0
- package/dist/utils/session-serialization.d.ts.map +1 -0
- package/dist/utils/session-serialization.js +217 -0
- package/dist/utils/session-serialization.js.map +1 -0
- package/dist/utils/workflow-error-utils.d.ts +22 -0
- package/dist/utils/workflow-error-utils.d.ts.map +1 -0
- package/dist/utils/workflow-error-utils.js +45 -0
- package/dist/utils/workflow-error-utils.js.map +1 -0
- package/package.json +34 -5
- package/.claude/commands/subtask-planning/prp-base-create.md +0 -120
- package/.claude/commands/subtask-planning/prp-base-execute.md +0 -65
- package/.claude/commands/task-breakdown.md +0 -94
- package/.claude/settings.local.json +0 -9
- package/.claude/system_prompts/task-breakdown.md +0 -101
- package/CHANGELOG.md +0 -188
- package/PRD.md +0 -543
- package/PRPs/001-hierarchical-workflow-engine.md +0 -2438
- package/PRPs/PRDs/002-agent-prompt.md +0 -390
- package/PRPs/PRDs/003-agent-prompt.md +0 -943
- package/PRPs/PRDs/004-agent-prompt.md +0 -1136
- package/PRPs/PRDs/tasks-001.json +0 -492
- package/PRPs/README.md +0 -83
- package/PRPs/templates/prp_base.md +0 -222
- package/docs/agent.md +0 -422
- package/docs/prompt.md +0 -419
- package/docs/workflow.md +0 -600
- package/examples/README.md +0 -258
- package/examples/examples/01-basic-workflow.ts +0 -100
- package/examples/examples/02-decorator-options.ts +0 -217
- package/examples/examples/03-parent-child.ts +0 -241
- package/examples/examples/04-observers-debugger.ts +0 -340
- package/examples/examples/05-error-handling.ts +0 -387
- package/examples/examples/06-concurrent-tasks.ts +0 -352
- package/examples/examples/07-agent-loops.ts +0 -432
- package/examples/examples/08-sdk-features.ts +0 -667
- package/examples/examples/09-reflection.ts +0 -573
- package/examples/examples/10-introspection.ts +0 -550
- package/examples/examples/11-reparenting-workflows.ts +0 -269
- package/examples/index.ts +0 -147
- package/examples/utils/helpers.ts +0 -57
- package/package-lock.json +0 -2398
- package/plan/001_d3bb02af4886/TEST_RESULTS.md +0 -259
- package/plan/001_d3bb02af4886/backlog.json +0 -867
- package/plan/001_d3bb02af4886/bug_fix_tasks.json +0 -484
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +0 -488
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +0 -581
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +0 -687
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +0 -492
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +0 -932
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +0 -1109
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +0 -802
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +0 -603
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +0 -564
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +0 -518
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +0 -1252
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +0 -364
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +0 -205
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +0 -199
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +0 -134
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +0 -495
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +0 -435
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +0 -558
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +0 -788
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +0 -460
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +0 -454
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +0 -520
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +0 -417
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +0 -245
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +0 -792
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +0 -535
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +0 -190
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +0 -654
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +0 -227
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +0 -345
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +0 -193
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +0 -1323
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +0 -1011
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +0 -927
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +0 -505
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +0 -401
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +0 -142
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +0 -112
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +0 -159
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +0 -549
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +0 -368
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +0 -172
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +0 -175
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +0 -696
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +0 -860
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +0 -1066
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +0 -789
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +0 -1098
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +0 -1037
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +0 -916
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +0 -1045
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +0 -890
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +0 -822
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +0 -668
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +0 -706
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +0 -655
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +0 -426
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +0 -316
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +0 -754
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +0 -719
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +0 -215
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +0 -765
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +0 -718
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +0 -149
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +0 -470
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +0 -332
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +0 -167
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +0 -273
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +0 -434
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +0 -717
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +0 -472
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +0 -125
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +0 -301
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +0 -1170
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +0 -940
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +0 -151
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +0 -650
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +0 -259
- package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +0 -457
- package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +0 -346
- package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +0 -311
- package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +0 -1565
- package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +0 -288
- package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +0 -741
- package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +0 -652
- package/plan/001_d3bb02af4886/docs/PRP/P1P2-PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/P3P4-PRP.md +0 -1388
- package/plan/001_d3bb02af4886/docs/PRP/P4P5-PRP.md +0 -1136
- package/plan/001_d3bb02af4886/docs/PRP/PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +0 -415
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +0 -378
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +0 -713
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +0 -370
- package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +0 -499
- package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +0 -230
- package/plan/001_d3bb02af4886/docs/architecture/external_deps.md +0 -358
- package/plan/001_d3bb02af4886/docs/architecture/system_context.md +0 -242
- package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +0 -1134
- package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +0 -179
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +0 -214
- package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +0 -529
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +0 -142
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +0 -304
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +0 -558
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +0 -256
- package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +0 -346
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +0 -415
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +0 -489
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +0 -218
- package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +0 -380
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +0 -1923
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +0 -319
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +0 -115
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +0 -134
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +0 -153
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +0 -132
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +0 -716
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +0 -186
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +0 -604
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +0 -213
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +0 -30
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +0 -56
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +0 -53
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +0 -49
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +0 -958
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +0 -339
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +0 -305
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +0 -433
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +0 -1574
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +0 -1014
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_BEST_PRACTICES.md +0 -1929
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_CODE_PATTERNS.md +0 -857
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_INTEGRATION_GUIDE.md +0 -738
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_RESEARCH_INDEX.md +0 -424
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_INDEX.md +0 -291
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_RESEARCH_REPORT.md +0 -1342
- package/plan/001_d3bb02af4886/docs/research/P1P2/RESEARCH_SUMMARY.md +0 -342
- package/plan/001_d3bb02af4886/docs/research/P1P2/anthropic-sdk.md +0 -174
- package/plan/001_d3bb02af4886/docs/research/P1P2/async-local-storage.md +0 -200
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-code-patterns.md +0 -1205
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-decision-matrix.md +0 -421
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-implementation-guide.md +0 -1341
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-integration-guide.md +0 -834
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-patterns.md +0 -1468
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-quick-reference.md +0 -558
- package/plan/001_d3bb02af4886/docs/research/P1P2/zod-schema.md +0 -152
- package/plan/001_d3bb02af4886/docs/research/P3P4/caching-lru.md +0 -116
- package/plan/001_d3bb02af4886/docs/research/P3P4/introspection-tools.md +0 -177
- package/plan/001_d3bb02af4886/docs/research/P3P4/reflection-patterns.md +0 -117
- package/plan/001_d3bb02af4886/docs/research/P4P5/RESEARCH_SUMMARY.md +0 -151
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +0 -376
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +0 -1507
- package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +0 -949
- package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +0 -619
- package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +0 -723
- package/plan/001_d3bb02af4886/docs/research/general/INTROSPECTION_RESEARCH_SUMMARY.md +0 -378
- package/plan/001_d3bb02af4886/docs/research/general/README-INTROSPECTION.md +0 -352
- package/plan/001_d3bb02af4886/docs/research/general/agent-introspection-patterns.md +0 -1085
- package/plan/001_d3bb02af4886/docs/research/general/introspection-security-guide.md +0 -984
- package/plan/001_d3bb02af4886/docs/research/general/introspection-tool-examples.md +0 -875
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +0 -460
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +0 -324
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +0 -175
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +0 -499
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +0 -163
- package/plan/001_d3bb02af4886/prd_snapshot.md +0 -543
- package/plan/bugfix/BUG_FIX_SUMMARY.md +0 -961
- package/scripts/generate-llms-full.ts +0 -206
- package/src/__tests__/adversarial/attachChild-performance.test.ts +0 -216
- package/src/__tests__/adversarial/circular-reference.test.ts +0 -101
- package/src/__tests__/adversarial/complex-circular-reference.test.ts +0 -139
- package/src/__tests__/adversarial/concurrent-task-failures.test.ts +0 -571
- package/src/__tests__/adversarial/deep-analysis.test.ts +0 -729
- package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +0 -213
- package/src/__tests__/adversarial/e2e-prd-validation.test.ts +0 -448
- package/src/__tests__/adversarial/edge-case.test.ts +0 -703
- package/src/__tests__/adversarial/error-merge-strategy.test.ts +0 -760
- package/src/__tests__/adversarial/incremental-performance.test.ts +0 -140
- package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +0 -457
- package/src/__tests__/adversarial/observer-propagation.test.ts +0 -487
- package/src/__tests__/adversarial/parent-validation.test.ts +0 -143
- package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +0 -611
- package/src/__tests__/adversarial/prd-compliance.test.ts +0 -731
- package/src/__tests__/compatibility/backward-compatibility.test.ts +0 -1572
- package/src/__tests__/helpers/index.ts +0 -18
- package/src/__tests__/helpers/tree-verification.ts +0 -257
- package/src/__tests__/integration/agent-workflow.test.ts +0 -256
- package/src/__tests__/integration/bidirectional-consistency.test.ts +0 -847
- package/src/__tests__/integration/observer-logging.test.ts +0 -643
- package/src/__tests__/integration/tree-mirroring.test.ts +0 -151
- package/src/__tests__/integration/workflow-reparenting.test.ts +0 -303
- package/src/__tests__/unit/agent.test.ts +0 -169
- package/src/__tests__/unit/cache-key.test.ts +0 -182
- package/src/__tests__/unit/cache.test.ts +0 -172
- package/src/__tests__/unit/context.test.ts +0 -217
- package/src/__tests__/unit/decorators.test.ts +0 -100
- package/src/__tests__/unit/introspection-tools.test.ts +0 -277
- package/src/__tests__/unit/logger.test.ts +0 -293
- package/src/__tests__/unit/observable.test.ts +0 -321
- package/src/__tests__/unit/prompt.test.ts +0 -135
- package/src/__tests__/unit/reflection.test.ts +0 -210
- package/src/__tests__/unit/tree-debugger-incremental.test.ts +0 -170
- package/src/__tests__/unit/tree-debugger.test.ts +0 -85
- package/src/__tests__/unit/utils/workflow-error-utils.test.ts +0 -209
- package/src/__tests__/unit/workflow-detachChild.test.ts +0 -100
- package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +0 -153
- package/src/__tests__/unit/workflow-isDescendantOf.test.ts +0 -180
- package/src/__tests__/unit/workflow.test.ts +0 -357
- package/src/cache/cache-key.ts +0 -244
- package/src/cache/cache.ts +0 -236
- package/src/core/agent.ts +0 -593
- package/src/core/event-tree.ts +0 -260
- package/src/core/logger.ts +0 -112
- package/src/core/mcp-handler.ts +0 -184
- package/src/core/prompt.ts +0 -150
- package/src/core/workflow-context.ts +0 -351
- package/src/core/workflow.ts +0 -540
- package/src/debugger/tree-debugger.ts +0 -255
- package/src/decorators/observed-state.ts +0 -95
- package/src/decorators/step.ts +0 -139
- package/src/decorators/task.ts +0 -159
- package/src/examples/tdd-orchestrator.ts +0 -65
- package/src/examples/test-cycle-workflow.ts +0 -64
- package/src/index.ts +0 -142
- package/src/reflection/reflection.ts +0 -407
- package/src/tools/index.ts +0 -36
- package/src/tools/introspection.ts +0 -464
- package/src/types/agent.ts +0 -90
- package/src/types/decorators.ts +0 -32
- package/src/types/error-strategy.ts +0 -13
- package/src/types/error.ts +0 -20
- package/src/types/events.ts +0 -75
- package/src/types/index.ts +0 -55
- package/src/types/logging.ts +0 -24
- package/src/types/observer.ts +0 -18
- package/src/types/prompt.ts +0 -40
- package/src/types/reflection.ts +0 -117
- package/src/types/sdk-primitives.ts +0 -128
- package/src/types/workflow-context.ts +0 -163
- package/src/types/workflow.ts +0 -37
- package/src/utils/id.ts +0 -11
- package/src/utils/index.ts +0 -4
- package/src/utils/observable.ts +0 -106
- package/src/utils/workflow-error-utils.ts +0 -56
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -16
|
@@ -1,754 +0,0 @@
|
|
|
1
|
-
# Vitest Best Practices for Testing Observer Error Logging
|
|
2
|
-
|
|
3
|
-
**Research Date:** 2026-01-12
|
|
4
|
-
**Task:** Research external best practices for testing observer error logging with vitest
|
|
5
|
-
**Status:** Complete
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Executive Summary
|
|
10
|
-
|
|
11
|
-
This research document compiles best practices for testing observer error logging patterns using Vitest, including:
|
|
12
|
-
|
|
13
|
-
1. Mocking and verifying logger usage (not console output)
|
|
14
|
-
2. Testing that errors don't crash execution
|
|
15
|
-
3. Testing observer pattern error handling
|
|
16
|
-
4. Verifying error context in logs
|
|
17
|
-
5. Official Vitest documentation with section anchors
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 1. Official Vitest Documentation URLs
|
|
22
|
-
|
|
23
|
-
### Core Documentation
|
|
24
|
-
|
|
25
|
-
| Resource | URL | Key Sections |
|
|
26
|
-
|----------|-----|--------------|
|
|
27
|
-
| **Vitest Main Docs** | https://vitest.dev/ | Overview, getting started |
|
|
28
|
-
| **Assertions API** | https://vitest.dev/api/expect.html | `toThrow()`, `toHaveBeenCalledWith()`, `objectContaining()` |
|
|
29
|
-
| **Mocking Guide** | https://vitest.dev/guide/mocking.html | `vi.fn()`, `vi.spyOn()`, mock implementations |
|
|
30
|
-
| **Async Testing** | https://vitest.dev/guide/async.html | `.resolves`, `.rejects` modifiers |
|
|
31
|
-
| **Test Context** | https://vitest.dev/api/context.html | `beforeEach()`, `afterEach()` setup |
|
|
32
|
-
| **Mock Functions** | https://vitest.dev/api/mock.html | Mock function APIs and expectations |
|
|
33
|
-
|
|
34
|
-
### Section-Specific Anchors
|
|
35
|
-
|
|
36
|
-
**Error Testing Assertions:**
|
|
37
|
-
- `toThrow()`: https://vitest.dev/api/expect.html#tothrow
|
|
38
|
-
- `.resolves` / `.rejects`: https://vitest.dev/api/expect.html#resolves
|
|
39
|
-
- Custom matchers: https://vitest.dev/api/expect.html#objectcontaining
|
|
40
|
-
|
|
41
|
-
**Mocking Patterns:**
|
|
42
|
-
- `vi.spyOn()`: https://vitest.dev/guide/mocking.html#spy-on
|
|
43
|
-
- `vi.fn()`: https://vitest.dev/guide/mocking.html#mock-functions
|
|
44
|
-
- Mock restoration: https://vitest.dev/guide/mocking.html#restoring-mocks
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## 2. Mocking Logger in Vitest (Not Console Output)
|
|
49
|
-
|
|
50
|
-
### Pattern 1: Mock Logger Interface
|
|
51
|
-
|
|
52
|
-
**Best Practice:** Create a logger interface and mock it, rather than spying on `console.error`.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
// Logger interface
|
|
56
|
-
export interface ObservableLogger {
|
|
57
|
-
error(message: string, data?: unknown): void;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Test with mock logger
|
|
61
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
62
|
-
|
|
63
|
-
describe('Observable error logging', () => {
|
|
64
|
-
let mockLogger: ObservableLogger;
|
|
65
|
-
|
|
66
|
-
beforeEach(() => {
|
|
67
|
-
mockLogger = {
|
|
68
|
-
error: vi.fn(),
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should log subscriber errors via logger', () => {
|
|
73
|
-
const observable = new Observable<number>(mockLogger);
|
|
74
|
-
const testError = new Error('Next error');
|
|
75
|
-
|
|
76
|
-
const throwingSubscriber = {
|
|
77
|
-
next: () => {
|
|
78
|
-
throw testError;
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
observable.subscribe(throwingSubscriber);
|
|
83
|
-
observable.next(42);
|
|
84
|
-
|
|
85
|
-
// Verify logger was called (not console)
|
|
86
|
-
expect(mockLogger.error).toHaveBeenCalledWith('Observable subscriber error', {
|
|
87
|
-
error: testError,
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/unit/observable.test.ts` (lines 14-30)
|
|
94
|
-
|
|
95
|
-
### Pattern 2: Verify Logger Call Count and Arguments
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
it('should log errors for multiple throwing subscribers', () => {
|
|
99
|
-
const observable = new Observable<number>(mockLogger);
|
|
100
|
-
const error1 = new Error('Error 1');
|
|
101
|
-
const error2 = new Error('Error 2');
|
|
102
|
-
|
|
103
|
-
const throwingSubscriber1 = { next: () => { throw error1; } };
|
|
104
|
-
const throwingSubscriber2 = { next: () => { throw error2; } };
|
|
105
|
-
|
|
106
|
-
observable.subscribe(throwingSubscriber1);
|
|
107
|
-
observable.subscribe(throwingSubscriber2);
|
|
108
|
-
observable.next(42);
|
|
109
|
-
|
|
110
|
-
// Verify call count
|
|
111
|
-
expect(mockLogger.error).toHaveBeenCalledTimes(2);
|
|
112
|
-
|
|
113
|
-
// Verify specific calls
|
|
114
|
-
expect(mockLogger.error).toHaveBeenNthCalledWith(1, 'Observable subscriber error', {
|
|
115
|
-
error: error1,
|
|
116
|
-
});
|
|
117
|
-
expect(mockLogger.error).toHaveBeenNthCalledWith(2, 'Observable subscriber error', {
|
|
118
|
-
error: error2,
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/unit/observable.test.ts` (lines 95-123)
|
|
124
|
-
|
|
125
|
-
### Pattern 3: Console Fallback Testing
|
|
126
|
-
|
|
127
|
-
When testing fallback to `console.error`, use `vi.spyOn()`:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
it('should fall back to console.error when no logger provided', () => {
|
|
131
|
-
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
132
|
-
const observable = new Observable<number>();
|
|
133
|
-
const testError = new Error('Next error');
|
|
134
|
-
|
|
135
|
-
const throwingSubscriber = { next: () => { throw testError; } };
|
|
136
|
-
|
|
137
|
-
observable.subscribe(throwingSubscriber);
|
|
138
|
-
observable.next(42);
|
|
139
|
-
|
|
140
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith('Observable subscriber error', testError);
|
|
141
|
-
consoleErrorSpy.mockRestore();
|
|
142
|
-
});
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/unit/observable.test.ts` (lines 127-143)
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## 3. Testing Errors Don't Crash Execution
|
|
150
|
-
|
|
151
|
-
### Pattern 1: Error Isolation Tests
|
|
152
|
-
|
|
153
|
-
**Best Practice:** Verify that observer errors are caught and logged, not propagated.
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
describe('Error isolation', () => {
|
|
157
|
-
let mockLogger: ObservableLogger;
|
|
158
|
-
|
|
159
|
-
beforeEach(() => {
|
|
160
|
-
mockLogger = { error: vi.fn() };
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should not propagate errors outside try-catch', () => {
|
|
164
|
-
const observable = new Observable<number>(mockLogger);
|
|
165
|
-
const testError = new Error('Subscriber error');
|
|
166
|
-
|
|
167
|
-
const throwingSubscriber = { next: () => { throw testError; } };
|
|
168
|
-
|
|
169
|
-
observable.subscribe(throwingSubscriber);
|
|
170
|
-
|
|
171
|
-
// This should NOT throw
|
|
172
|
-
expect(() => {
|
|
173
|
-
observable.next(42);
|
|
174
|
-
}).not.toThrow();
|
|
175
|
-
|
|
176
|
-
// But error should be logged
|
|
177
|
-
expect(mockLogger.error).toHaveBeenCalled();
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/unit/observable.test.ts` (lines 252-279)
|
|
183
|
-
|
|
184
|
-
### Pattern 2: Continue Notifying Other Observers
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
it('should continue notifying other subscribers after one throws', () => {
|
|
188
|
-
const observable = new Observable<number>(mockLogger);
|
|
189
|
-
const testError = new Error('First subscriber error');
|
|
190
|
-
const results: number[] = [];
|
|
191
|
-
|
|
192
|
-
const throwingSubscriber = { next: () => { throw testError; } };
|
|
193
|
-
|
|
194
|
-
const workingSubscriber = {
|
|
195
|
-
next: (value: number) => {
|
|
196
|
-
results.push(value);
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
observable.subscribe(throwingSubscriber);
|
|
201
|
-
observable.subscribe(workingSubscriber);
|
|
202
|
-
observable.next(42);
|
|
203
|
-
|
|
204
|
-
// Verify working subscriber received value
|
|
205
|
-
expect(results).toEqual([42]);
|
|
206
|
-
// Verify error was logged
|
|
207
|
-
expect(mockLogger.error).toHaveBeenCalled();
|
|
208
|
-
});
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/unit/observable.test.ts` (lines 69-93)
|
|
212
|
-
|
|
213
|
-
### Pattern 3: Workflow Observer Error Isolation
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
it('should not crash workflow when observer onLog throws', async () => {
|
|
217
|
-
const throwingObserver: WorkflowObserver = {
|
|
218
|
-
onLog: () => {
|
|
219
|
-
throw new Error('Observer onLog error');
|
|
220
|
-
},
|
|
221
|
-
onEvent: () => {},
|
|
222
|
-
onStateUpdated: () => {},
|
|
223
|
-
onTreeChanged: () => {},
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
class TestWorkflow extends Workflow {
|
|
227
|
-
async run() {
|
|
228
|
-
this.logger.info('Message 1');
|
|
229
|
-
this.logger.info('Message 2');
|
|
230
|
-
this.logger.info('Message 3');
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const workflow = new TestWorkflow();
|
|
235
|
-
workflow.addObserver(throwingObserver);
|
|
236
|
-
|
|
237
|
-
// Should complete without throwing
|
|
238
|
-
await expect(workflow.run()).resolves.toBeUndefined();
|
|
239
|
-
|
|
240
|
-
// All messages should be logged
|
|
241
|
-
expect(workflow.node.logs.length).toBe(6); // 3 messages + 3 error logs
|
|
242
|
-
});
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 242-268)
|
|
246
|
-
|
|
247
|
-
---
|
|
248
|
-
|
|
249
|
-
## 4. Testing Observer Pattern Error Handling
|
|
250
|
-
|
|
251
|
-
### Pattern 1: Multiple Observers with Some Failing
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
it('should continue notifying other observers after one throws', async () => {
|
|
255
|
-
let observer2Called = false;
|
|
256
|
-
let observer3Called = false;
|
|
257
|
-
|
|
258
|
-
const throwingObserver: WorkflowObserver = {
|
|
259
|
-
onLog: () => {
|
|
260
|
-
throw new Error('Observer 1 failed');
|
|
261
|
-
},
|
|
262
|
-
onEvent: () => {},
|
|
263
|
-
onStateUpdated: () => {},
|
|
264
|
-
onTreeChanged: () => {},
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
const workingObserver2: WorkflowObserver = {
|
|
268
|
-
onLog: () => {
|
|
269
|
-
observer2Called = true;
|
|
270
|
-
},
|
|
271
|
-
onEvent: () => {},
|
|
272
|
-
onStateUpdated: () => {},
|
|
273
|
-
onTreeChanged: () => {},
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const workingObserver3: WorkflowObserver = {
|
|
277
|
-
onLog: () => {
|
|
278
|
-
observer3Called = true;
|
|
279
|
-
},
|
|
280
|
-
onEvent: () => {},
|
|
281
|
-
onStateUpdated: () => {},
|
|
282
|
-
onTreeChanged: () => {},
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
class TestWorkflow extends Workflow {
|
|
286
|
-
async run() {
|
|
287
|
-
this.logger.info('Test message');
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const workflow = new TestWorkflow();
|
|
292
|
-
workflow.addObserver(throwingObserver);
|
|
293
|
-
workflow.addObserver(workingObserver2);
|
|
294
|
-
workflow.addObserver(workingObserver3);
|
|
295
|
-
|
|
296
|
-
await workflow.run();
|
|
297
|
-
|
|
298
|
-
// Both working observers should have been called
|
|
299
|
-
expect(observer2Called).toBe(true);
|
|
300
|
-
expect(observer3Called).toBe(true);
|
|
301
|
-
|
|
302
|
-
// Should have error log for throwing observer
|
|
303
|
-
const errorLog = workflow.node.logs.find((log) => log.message === 'Observer onLog error');
|
|
304
|
-
expect(errorLog).toBeDefined();
|
|
305
|
-
});
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 327-378)
|
|
309
|
-
|
|
310
|
-
### Pattern 2: Log Errors from Multiple Throwing Observers
|
|
311
|
-
|
|
312
|
-
```typescript
|
|
313
|
-
it('should log errors for multiple throwing observers', async () => {
|
|
314
|
-
const throwingObserver1: WorkflowObserver = {
|
|
315
|
-
onLog: () => {
|
|
316
|
-
throw new Error('Observer 1 error');
|
|
317
|
-
},
|
|
318
|
-
onEvent: () => {},
|
|
319
|
-
onStateUpdated: () => {},
|
|
320
|
-
onTreeChanged: () => {},
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
const throwingObserver2: WorkflowObserver = {
|
|
324
|
-
onLog: () => {
|
|
325
|
-
throw new Error('Observer 2 error');
|
|
326
|
-
},
|
|
327
|
-
onEvent: () => {},
|
|
328
|
-
onStateUpdated: () => {},
|
|
329
|
-
onTreeChanged: () => {},
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
class TestWorkflow extends Workflow {
|
|
333
|
-
async run() {
|
|
334
|
-
this.logger.info('Test message');
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const workflow = new TestWorkflow();
|
|
339
|
-
workflow.addObserver(throwingObserver1);
|
|
340
|
-
workflow.addObserver(throwingObserver2);
|
|
341
|
-
|
|
342
|
-
await workflow.run();
|
|
343
|
-
|
|
344
|
-
// Should have error logs for both throwing observers
|
|
345
|
-
const errorLogs = workflow.node.logs.filter((log) => log.message === 'Observer onLog error');
|
|
346
|
-
expect(errorLogs.length).toBe(2);
|
|
347
|
-
});
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 380-414)
|
|
351
|
-
|
|
352
|
-
### Pattern 3: Avoid Infinite Recursion
|
|
353
|
-
|
|
354
|
-
```typescript
|
|
355
|
-
it('should avoid infinite recursion when observer onLog throws', async () => {
|
|
356
|
-
let callCount = 0;
|
|
357
|
-
const maxCalls = 10; // Safety limit to prevent actual infinite loop
|
|
358
|
-
|
|
359
|
-
const throwingObserver: WorkflowObserver = {
|
|
360
|
-
onLog: () => {
|
|
361
|
-
callCount++;
|
|
362
|
-
if (callCount < maxCalls) {
|
|
363
|
-
throw new Error('Recursive error');
|
|
364
|
-
}
|
|
365
|
-
},
|
|
366
|
-
onEvent: () => {},
|
|
367
|
-
onStateUpdated: () => {},
|
|
368
|
-
onTreeChanged: () => {},
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
class TestWorkflow extends Workflow {
|
|
372
|
-
async run() {
|
|
373
|
-
this.logger.info('Test message');
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
const workflow = new TestWorkflow();
|
|
378
|
-
workflow.addObserver(throwingObserver);
|
|
379
|
-
await workflow.run();
|
|
380
|
-
|
|
381
|
-
// Should only call onLog once (original) + one error log, then stop
|
|
382
|
-
// The error log should NOT trigger another observer notification
|
|
383
|
-
expect(callCount).toBe(1);
|
|
384
|
-
|
|
385
|
-
// Should have 2 logs: original + error
|
|
386
|
-
expect(workflow.node.logs.length).toBe(2);
|
|
387
|
-
});
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 42-74)
|
|
391
|
-
|
|
392
|
-
---
|
|
393
|
-
|
|
394
|
-
## 5. Verifying Error Context in Logs
|
|
395
|
-
|
|
396
|
-
### Pattern 1: Verify Error Object in Log Data
|
|
397
|
-
|
|
398
|
-
```typescript
|
|
399
|
-
it('should log observer onLog errors to workflow.node.logs', async () => {
|
|
400
|
-
const onLogError = new Error('Observer onLog failed');
|
|
401
|
-
|
|
402
|
-
const throwingObserver: WorkflowObserver = {
|
|
403
|
-
onLog: () => {
|
|
404
|
-
throw onLogError;
|
|
405
|
-
},
|
|
406
|
-
onEvent: () => {},
|
|
407
|
-
onStateUpdated: () => {},
|
|
408
|
-
onTreeChanged: () => {},
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
class TestWorkflow extends Workflow {
|
|
412
|
-
async run() {
|
|
413
|
-
this.logger.info('Test message');
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const workflow = new TestWorkflow();
|
|
418
|
-
workflow.addObserver(throwingObserver);
|
|
419
|
-
await workflow.run();
|
|
420
|
-
|
|
421
|
-
// Should have 2 logs: the original "Test message" and the observer error
|
|
422
|
-
expect(workflow.node.logs.length).toBe(2);
|
|
423
|
-
|
|
424
|
-
// First log is the original message
|
|
425
|
-
expect(workflow.node.logs[0].message).toBe('Test message');
|
|
426
|
-
expect(workflow.node.logs[0].level).toBe('info');
|
|
427
|
-
|
|
428
|
-
// Second log is the observer error
|
|
429
|
-
expect(workflow.node.logs[1].message).toBe('Observer onLog error');
|
|
430
|
-
expect(workflow.node.logs[1].level).toBe('error');
|
|
431
|
-
expect(workflow.node.logs[1].data).toEqual({ error: onLogError });
|
|
432
|
-
});
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 7-40)
|
|
436
|
-
|
|
437
|
-
### Pattern 2: Include Event Type in Error Data
|
|
438
|
-
|
|
439
|
-
```typescript
|
|
440
|
-
it('should include event type in error data', () => {
|
|
441
|
-
const throwingObserver: WorkflowObserver = {
|
|
442
|
-
onLog: () => {},
|
|
443
|
-
onEvent: () => {
|
|
444
|
-
throw new Error('Event error');
|
|
445
|
-
},
|
|
446
|
-
onStateUpdated: () => {},
|
|
447
|
-
onTreeChanged: () => {},
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
class TestWorkflow extends Workflow {
|
|
451
|
-
async run() {
|
|
452
|
-
this.emitEvent({ type: 'treeUpdated', root: this.node });
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
const workflow = new TestWorkflow();
|
|
457
|
-
workflow.addObserver(throwingObserver);
|
|
458
|
-
|
|
459
|
-
workflow.run();
|
|
460
|
-
|
|
461
|
-
const errorLog = workflow.node.logs.find((log) => log.message === 'Observer onEvent error');
|
|
462
|
-
expect(errorLog?.data).toHaveProperty('eventType', 'treeUpdated');
|
|
463
|
-
});
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 111-134)
|
|
467
|
-
|
|
468
|
-
### Pattern 3: Include Node ID in Error Data
|
|
469
|
-
|
|
470
|
-
```typescript
|
|
471
|
-
it('should include node ID in error data', async () => {
|
|
472
|
-
const throwingObserver: WorkflowObserver = {
|
|
473
|
-
onLog: () => {},
|
|
474
|
-
onEvent: () => {},
|
|
475
|
-
onStateUpdated: () => {
|
|
476
|
-
throw new Error('State update error');
|
|
477
|
-
},
|
|
478
|
-
onTreeChanged: () => {},
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
class TestWorkflow extends Workflow {
|
|
482
|
-
async run() {
|
|
483
|
-
this.snapshotState();
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const workflow = new TestWorkflow();
|
|
488
|
-
workflow.addObserver(throwingObserver);
|
|
489
|
-
await workflow.run();
|
|
490
|
-
|
|
491
|
-
const errorLog = workflow.node.logs.find(
|
|
492
|
-
(log) => log.message === 'Observer onStateUpdated error'
|
|
493
|
-
);
|
|
494
|
-
expect(errorLog?.data).toHaveProperty('nodeId', workflow.node.id);
|
|
495
|
-
});
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 172-196)
|
|
499
|
-
|
|
500
|
-
### Pattern 4: Verify Structured Error Context
|
|
501
|
-
|
|
502
|
-
```typescript
|
|
503
|
-
it('should log structured error context', async () => {
|
|
504
|
-
const events: WorkflowEvent[] = [];
|
|
505
|
-
|
|
506
|
-
const throwingObserver: WorkflowObserver = {
|
|
507
|
-
onEvent: () => {
|
|
508
|
-
throw new Error('Observer onEvent failed');
|
|
509
|
-
},
|
|
510
|
-
onLog: () => {},
|
|
511
|
-
onStateUpdated: () => {},
|
|
512
|
-
onTreeChanged: () => {},
|
|
513
|
-
};
|
|
514
|
-
|
|
515
|
-
class TestWorkflow extends Workflow {
|
|
516
|
-
async run() {
|
|
517
|
-
this.emitEvent({ type: 'testEvent' });
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
const workflow = new TestWorkflow();
|
|
522
|
-
workflow.addObserver(throwingObserver);
|
|
523
|
-
|
|
524
|
-
workflow.run();
|
|
525
|
-
|
|
526
|
-
// Should have error log entry
|
|
527
|
-
const errorLog = workflow.node.logs.find((log) => log.message === 'Observer onEvent error');
|
|
528
|
-
expect(errorLog).toBeDefined();
|
|
529
|
-
expect(errorLog?.level).toBe('error');
|
|
530
|
-
expect(errorLog?.data).toEqual({
|
|
531
|
-
error: expect.any(Error),
|
|
532
|
-
eventType: 'testEvent',
|
|
533
|
-
});
|
|
534
|
-
});
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
**Source:** `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` (lines 77-109)
|
|
538
|
-
|
|
539
|
-
---
|
|
540
|
-
|
|
541
|
-
## 6. Mocking Patterns for Loggers in Vitest
|
|
542
|
-
|
|
543
|
-
### Pattern 1: beforeEach/afterEach Setup
|
|
544
|
-
|
|
545
|
-
**Best Practice:** Always restore mocks in cleanup.
|
|
546
|
-
|
|
547
|
-
```typescript
|
|
548
|
-
describe('Logger tests', () => {
|
|
549
|
-
let mockLogger: ObservableLogger;
|
|
550
|
-
let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
|
|
551
|
-
|
|
552
|
-
beforeEach(() => {
|
|
553
|
-
mockLogger = {
|
|
554
|
-
error: vi.fn(),
|
|
555
|
-
};
|
|
556
|
-
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
afterEach(() => {
|
|
560
|
-
consoleErrorSpy.mockRestore();
|
|
561
|
-
vi.restoreAllMocks();
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
it('test case', () => {
|
|
565
|
-
// mockLogger and consoleErrorSpy are already set up
|
|
566
|
-
});
|
|
567
|
-
});
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
### Pattern 2: Partial Mocking
|
|
571
|
-
|
|
572
|
-
```typescript
|
|
573
|
-
// Mock only specific methods
|
|
574
|
-
const mockLogger = {
|
|
575
|
-
error: vi.fn(),
|
|
576
|
-
info: vi.fn(),
|
|
577
|
-
warn: vi.fn(),
|
|
578
|
-
debug: vi.fn(),
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
// Use in tests
|
|
582
|
-
expect(mockLogger.error).toHaveBeenCalledWith('message', { context: 'value' });
|
|
583
|
-
expect(mockLogger.error).toHaveBeenCalledTimes(1);
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
### Pattern 3: Module Mocking
|
|
587
|
-
|
|
588
|
-
```typescript
|
|
589
|
-
// Mock entire logger module
|
|
590
|
-
vi.mock('./logger', () => ({
|
|
591
|
-
logger: {
|
|
592
|
-
info: vi.fn(),
|
|
593
|
-
error: vi.fn(),
|
|
594
|
-
warn: vi.fn(),
|
|
595
|
-
debug: vi.fn(),
|
|
596
|
-
},
|
|
597
|
-
}));
|
|
598
|
-
|
|
599
|
-
import { logger } from './logger';
|
|
600
|
-
|
|
601
|
-
describe('Module mocking', () => {
|
|
602
|
-
it('should use mocked logger', () => {
|
|
603
|
-
logger.info('test');
|
|
604
|
-
expect(logger.info).toHaveBeenCalledWith('test');
|
|
605
|
-
});
|
|
606
|
-
});
|
|
607
|
-
```
|
|
608
|
-
|
|
609
|
-
---
|
|
610
|
-
|
|
611
|
-
## 7. Best Practices Summary
|
|
612
|
-
|
|
613
|
-
### DO's
|
|
614
|
-
|
|
615
|
-
1. **Mock logger interfaces, not console output**
|
|
616
|
-
```typescript
|
|
617
|
-
const mockLogger = { error: vi.fn() };
|
|
618
|
-
expect(mockLogger.error).toHaveBeenCalledWith(...);
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
2. **Verify errors don't crash execution**
|
|
622
|
-
```typescript
|
|
623
|
-
expect(() => observable.next(42)).not.toThrow();
|
|
624
|
-
expect(mockLogger.error).toHaveBeenCalled();
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
3. **Test multiple observers with mixed success/failure**
|
|
628
|
-
```typescript
|
|
629
|
-
// Some throw, some succeed
|
|
630
|
-
expect(observer2Called).toBe(true);
|
|
631
|
-
expect(errorLogs.length).toBe(2);
|
|
632
|
-
```
|
|
633
|
-
|
|
634
|
-
4. **Verify error context in logs**
|
|
635
|
-
```typescript
|
|
636
|
-
expect(errorLog.data).toEqual({
|
|
637
|
-
error: expect.any(Error),
|
|
638
|
-
eventType: 'testEvent',
|
|
639
|
-
});
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
5. **Always restore mocks**
|
|
643
|
-
```typescript
|
|
644
|
-
afterEach(() => {
|
|
645
|
-
consoleSpy.mockRestore();
|
|
646
|
-
vi.restoreAllMocks();
|
|
647
|
-
});
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
### DON'Ts
|
|
651
|
-
|
|
652
|
-
1. **Don't test console.output directly for logger verification**
|
|
653
|
-
```typescript
|
|
654
|
-
// BAD
|
|
655
|
-
expect(console.error).toHaveBeenCalledWith(...);
|
|
656
|
-
|
|
657
|
-
// GOOD
|
|
658
|
-
expect(mockLogger.error).toHaveBeenCalledWith(...);
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
2. **Don't forget to test error isolation**
|
|
662
|
-
```typescript
|
|
663
|
-
// BAD - only tests error thrown
|
|
664
|
-
expect(() => observable.next(42)).toThrow();
|
|
665
|
-
|
|
666
|
-
// GOOD - tests error caught and logged
|
|
667
|
-
expect(() => observable.next(42)).not.toThrow();
|
|
668
|
-
expect(mockLogger.error).toHaveBeenCalled();
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
3. **Don't skip testing multiple observers**
|
|
672
|
-
```typescript
|
|
673
|
-
// Test with 3+ observers to ensure isolation
|
|
674
|
-
```
|
|
675
|
-
|
|
676
|
-
4. **Don't ignore error context verification**
|
|
677
|
-
```typescript
|
|
678
|
-
// Verify error objects, not just messages
|
|
679
|
-
expect(errorLog.data.error).toBeInstanceOf(Error);
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
---
|
|
683
|
-
|
|
684
|
-
## 8. Quick Reference: Vitest Assertions for Logger Testing
|
|
685
|
-
|
|
686
|
-
```typescript
|
|
687
|
-
// Mock logger creation
|
|
688
|
-
const mockLogger = { error: vi.fn() };
|
|
689
|
-
|
|
690
|
-
// Verify logger was called
|
|
691
|
-
expect(mockLogger.error).toHaveBeenCalled();
|
|
692
|
-
expect(mockLogger.error).toHaveBeenCalledTimes(1);
|
|
693
|
-
expect(mockLogger.error).toHaveBeenCalledWith('message', { error });
|
|
694
|
-
|
|
695
|
-
// Verify specific call
|
|
696
|
-
expect(mockLogger.error).toHaveBeenNthCalledWith(1, 'message', { error: expect.any(Error) });
|
|
697
|
-
|
|
698
|
-
// Verify error isolation
|
|
699
|
-
expect(() => observable.next(42)).not.toThrow();
|
|
700
|
-
|
|
701
|
-
// Verify log data structure
|
|
702
|
-
expect(logEntry.data).toEqual({
|
|
703
|
-
error: expect.any(Error),
|
|
704
|
-
eventType: 'testEvent',
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
// Console fallback testing
|
|
708
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
709
|
-
expect(consoleSpy).toHaveBeenCalledWith('message', error);
|
|
710
|
-
consoleSpy.mockRestore();
|
|
711
|
-
```
|
|
712
|
-
|
|
713
|
-
---
|
|
714
|
-
|
|
715
|
-
## 9. External Resources
|
|
716
|
-
|
|
717
|
-
### Vitest Official Documentation
|
|
718
|
-
- Main: https://vitest.dev/
|
|
719
|
-
- Assertions: https://vitest.dev/api/expect.html
|
|
720
|
-
- Mocking: https://vitest.dev/guide/mocking.html
|
|
721
|
-
- Async: https://vitest.dev/guide/async.html
|
|
722
|
-
|
|
723
|
-
### Observer Pattern Resources
|
|
724
|
-
- Observer pattern error handling: https://en.wikipedia.org/wiki/Observer_pattern
|
|
725
|
-
- Testing observer patterns: https://refactoring.guru/design-patterns/observer
|
|
726
|
-
|
|
727
|
-
### Error Handling Best Practices
|
|
728
|
-
- Structured logging: https://www.loggly.com/blog/structured-logging-best-practices/
|
|
729
|
-
- Error context capture: https://planetaria.co/blog/capturing-error-context-in-javascript
|
|
730
|
-
|
|
731
|
-
---
|
|
732
|
-
|
|
733
|
-
## 10. Related Files in Groundswell Project
|
|
734
|
-
|
|
735
|
-
### Test Files (Reference Implementations)
|
|
736
|
-
- `/home/dustin/projects/groundswell/src/__tests__/integration/observer-logging.test.ts` - Observer error logging integration tests
|
|
737
|
-
- `/home/dustin/projects/groundswell/src/__tests__/unit/observable.test.ts` - Observable error handling unit tests
|
|
738
|
-
- `/home/dustin/projects/groundswell/src/__tests__/unit/workflow.test.ts` - Workflow error state tests
|
|
739
|
-
|
|
740
|
-
### Source Files (Implementation)
|
|
741
|
-
- `/home/dustin/projects/groundswell/src/utils/observable.ts` - Observable class with logger injection
|
|
742
|
-
- `/home/dustin/projects/groundswell/src/core/logger.ts` - WorkflowLogger implementation
|
|
743
|
-
- `/home/dustin/projects/groundswell/src/core/workflow.ts` - Workflow class with observer error handling
|
|
744
|
-
|
|
745
|
-
### Research Documents
|
|
746
|
-
- `/home/dustin/projects/groundswell/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md` - Vitest testing patterns
|
|
747
|
-
- `/home/dustin/projects/groundswell/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md` - Concurrent testing patterns
|
|
748
|
-
- `/home/dustin/projects/groundswell/plan/001_d3bb02af4886/docs/research/error-testing-research.md` - Error state capture research
|
|
749
|
-
|
|
750
|
-
---
|
|
751
|
-
|
|
752
|
-
**Document Version:** 1.0
|
|
753
|
-
**Last Updated:** 2026-01-12
|
|
754
|
-
**Research Summary:** Comprehensive best practices for testing observer error logging in Vitest
|