xtrm-tools 2.3.0 → 2.4.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/README.md +127 -111
- package/cli/dist/index.cjs +107 -53
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/config/pi/extensions/beads.ts +24 -0
- package/hooks/beads-gate-core.mjs +6 -4
- package/hooks/beads-memory-gate.mjs +12 -5
- package/hooks/hooks.json +126 -0
- package/package.json +3 -1
- package/skills/test-planning/SKILL.md +208 -0
- package/skills/test-planning/evals/evals.json +23 -0
- package/skills/using-xtrm/SKILL.md +5 -27
- package/project-skills/tdd-guard/.claude/hooks/tdd-guard-pretool-bridge.cjs +0 -103
- package/project-skills/tdd-guard/.claude/settings.json +0 -38
- package/project-skills/tdd-guard/.claude/skills/using-tdd-guard/SKILL.md +0 -79
- package/project-skills/tdd-guard/CLAUDE.md +0 -98
- package/project-skills/tdd-guard/CONTRIBUTING.md +0 -38
- package/project-skills/tdd-guard/DEVELOPMENT.md +0 -127
- package/project-skills/tdd-guard/LICENSE +0 -21
- package/project-skills/tdd-guard/README.md +0 -398
- package/project-skills/tdd-guard/docs/adr/001-claude-session-subdirectory.md +0 -52
- package/project-skills/tdd-guard/docs/adr/002-secure-claude-binary-path.md +0 -56
- package/project-skills/tdd-guard/docs/adr/003-remove-configurable-data-directory.md +0 -56
- package/project-skills/tdd-guard/docs/adr/004-monorepo-architecture.md +0 -64
- package/project-skills/tdd-guard/docs/adr/005-claude-project-dir-support.md +0 -55
- package/project-skills/tdd-guard/docs/adr/006-phpunit-separate-repository.md +0 -93
- package/project-skills/tdd-guard/docs/adr/007-golangci-lint-path-support.md +0 -83
- package/project-skills/tdd-guard/docs/adr/008-storybook-reporter-design.md +0 -182
- package/project-skills/tdd-guard/docs/assets/tdd-guard-demo-screenshot.gif +0 -0
- package/project-skills/tdd-guard/docs/config-migration.md +0 -143
- package/project-skills/tdd-guard/docs/configuration.md +0 -137
- package/project-skills/tdd-guard/docs/custom-instructions.md +0 -43
- package/project-skills/tdd-guard/docs/enforcement.md +0 -46
- package/project-skills/tdd-guard/docs/ignore-patterns.md +0 -81
- package/project-skills/tdd-guard/docs/linting.md +0 -109
- package/project-skills/tdd-guard/docs/quick-commands.md +0 -52
- package/project-skills/tdd-guard/docs/session-management.md +0 -75
- package/project-skills/tdd-guard/docs/storybook-vitest-addon.md +0 -120
- package/project-skills/tdd-guard/docs/validation-model.md +0 -63
- package/project-skills/tdd-guard/eslint.config.mjs +0 -140
- package/project-skills/tdd-guard/package-lock.json +0 -16937
- package/project-skills/tdd-guard/package.json +0 -102
- package/project-skills/tdd-guard/reporters/go/README.md +0 -67
- package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main.go +0 -127
- package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main_test.go +0 -280
- package/project-skills/tdd-guard/reporters/go/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/go/go.sum +0 -0
- package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter.go +0 -126
- package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter_test.go +0 -264
- package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader.go +0 -26
- package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader_test.go +0 -37
- package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader.go +0 -94
- package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader_test.go +0 -198
- package/project-skills/tdd-guard/reporters/go/internal/parser/parser.go +0 -245
- package/project-skills/tdd-guard/reporters/go/internal/parser/parser_test.go +0 -547
- package/project-skills/tdd-guard/reporters/go/internal/storage/storage.go +0 -35
- package/project-skills/tdd-guard/reporters/go/internal/storage/storage_test.go +0 -113
- package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer.go +0 -103
- package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer_test.go +0 -303
- package/project-skills/tdd-guard/reporters/jest/README.md +0 -102
- package/project-skills/tdd-guard/reporters/jest/package.json +0 -38
- package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test-data.ts +0 -199
- package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test.ts +0 -302
- package/project-skills/tdd-guard/reporters/jest/src/JestReporter.ts +0 -201
- package/project-skills/tdd-guard/reporters/jest/src/index.ts +0 -4
- package/project-skills/tdd-guard/reporters/jest/src/types.ts +0 -42
- package/project-skills/tdd-guard/reporters/jest/tsconfig.json +0 -11
- package/project-skills/tdd-guard/reporters/phpunit/.php-cs-fixer.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/README.md +0 -97
- package/project-skills/tdd-guard/reporters/phpunit/SYNC_README.md +0 -29
- package/project-skills/tdd-guard/reporters/phpunit/composer.json +0 -55
- package/project-skills/tdd-guard/reporters/phpunit/phpunit.xml.dist +0 -19
- package/project-skills/tdd-guard/reporters/phpunit/psalm.xml +0 -44
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/ErroredTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/FailedTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/IncompleteTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/PassedTestSubscriber.php +0 -27
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/SkippedTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/TestRunnerFinishedSubscriber.php +0 -24
- package/project-skills/tdd-guard/reporters/phpunit/src/PathValidator.php +0 -88
- package/project-skills/tdd-guard/reporters/phpunit/src/Storage.php +0 -26
- package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardExtension.php +0 -33
- package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardListener.php +0 -158
- package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardSubscriber.php +0 -35
- package/project-skills/tdd-guard/reporters/phpunit/src/TestResultCollector.php +0 -105
- package/project-skills/tdd-guard/reporters/phpunit/tests/PathValidatorTest.php +0 -74
- package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionFailedTest.php +0 -241
- package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionTest.php +0 -84
- package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardStorageLocationTest.php +0 -71
- package/project-skills/tdd-guard/reporters/pytest/README.md +0 -77
- package/project-skills/tdd-guard/reporters/pytest/pyproject.toml +0 -43
- package/project-skills/tdd-guard/reporters/pytest/pytest.ini.example +0 -7
- package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/__init__.py +0 -1
- package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/pytest_reporter.py +0 -134
- package/project-skills/tdd-guard/reporters/pytest/tests/__init__.py +0 -1
- package/project-skills/tdd-guard/reporters/pytest/tests/conftest.py +0 -3
- package/project-skills/tdd-guard/reporters/pytest/tests/helpers.py +0 -293
- package/project-skills/tdd-guard/reporters/pytest/tests/test_config_option.py +0 -38
- package/project-skills/tdd-guard/reporters/pytest/tests/test_path_validation.py +0 -59
- package/project-skills/tdd-guard/reporters/pytest/tests/test_plugin_config.py +0 -32
- package/project-skills/tdd-guard/reporters/pytest/tests/test_project_root.py +0 -296
- package/project-skills/tdd-guard/reporters/pytest/tests/test_pytest_reporter.py +0 -137
- package/project-skills/tdd-guard/reporters/rspec/Gemfile +0 -3
- package/project-skills/tdd-guard/reporters/rust/Cargo.lock +0 -458
- package/project-skills/tdd-guard/reporters/rust/Cargo.toml +0 -33
- package/project-skills/tdd-guard/reporters/rust/Makefile.example +0 -95
- package/project-skills/tdd-guard/reporters/rust/README.md +0 -88
- package/project-skills/tdd-guard/reporters/rust/src/error_parser.rs +0 -309
- package/project-skills/tdd-guard/reporters/rust/src/main.rs +0 -464
- package/project-skills/tdd-guard/reporters/rust/src/parser.rs +0 -225
- package/project-skills/tdd-guard/reporters/rust/src/transformer.rs +0 -409
- package/project-skills/tdd-guard/reporters/storybook/README.md +0 -108
- package/project-skills/tdd-guard/reporters/storybook/package-lock.json +0 -9482
- package/project-skills/tdd-guard/reporters/storybook/package.json +0 -43
- package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test-data.ts +0 -22
- package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test.ts +0 -190
- package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.ts +0 -88
- package/project-skills/tdd-guard/reporters/storybook/src/index.ts +0 -12
- package/project-skills/tdd-guard/reporters/storybook/src/types.ts +0 -37
- package/project-skills/tdd-guard/reporters/storybook/tsconfig.json +0 -11
- package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/single_failing_test.go +0 -13
- package/project-skills/tdd-guard/reporters/test/artifacts/go/import/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/go/import/single_import_error_test.go +0 -17
- package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/single_passing_test.go +0 -13
- package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-failing.test.js +0 -5
- package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-import-error.test.js +0 -8
- package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-passing.test.js +0 -5
- package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleFailingTest.php +0 -11
- package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleImportErrorTest.php +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SinglePassingTest.php +0 -11
- package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_failing.py +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_import_error.py +0 -6
- package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_passing.py +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.lock +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.toml +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/src/lib.rs +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.lock +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.toml +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/src/lib.rs +0 -13
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.lock +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.toml +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/src/lib.rs +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/Calculator.js +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-failing.stories.js +0 -15
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-import-error.stories.js +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-passing.stories.js +0 -15
- package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-failing.test.js +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-import-error.test.js +0 -9
- package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-passing.test.js +0 -7
- package/project-skills/tdd-guard/reporters/test/factories/go.ts +0 -59
- package/project-skills/tdd-guard/reporters/test/factories/helpers.ts +0 -48
- package/project-skills/tdd-guard/reporters/test/factories/index.ts +0 -7
- package/project-skills/tdd-guard/reporters/test/factories/jest.ts +0 -51
- package/project-skills/tdd-guard/reporters/test/factories/phpunit.ts +0 -63
- package/project-skills/tdd-guard/reporters/test/factories/pytest.ts +0 -41
- package/project-skills/tdd-guard/reporters/test/factories/rust.ts +0 -158
- package/project-skills/tdd-guard/reporters/test/factories/storybook.ts +0 -198
- package/project-skills/tdd-guard/reporters/test/factories/vitest.ts +0 -51
- package/project-skills/tdd-guard/reporters/test/reporters.integration.test.ts +0 -735
- package/project-skills/tdd-guard/reporters/test/types.ts +0 -28
- package/project-skills/tdd-guard/reporters/vitest/README.md +0 -64
- package/project-skills/tdd-guard/reporters/vitest/package.json +0 -35
- package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test-data.ts +0 -85
- package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test.ts +0 -446
- package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.ts +0 -110
- package/project-skills/tdd-guard/reporters/vitest/src/index.ts +0 -4
- package/project-skills/tdd-guard/reporters/vitest/src/types.ts +0 -39
- package/project-skills/tdd-guard/reporters/vitest/tsconfig.json +0 -11
- package/project-skills/tdd-guard/src/cli/buildContext.test.ts +0 -200
- package/project-skills/tdd-guard/src/cli/buildContext.ts +0 -48
- package/project-skills/tdd-guard/src/cli/tdd-guard.test.ts +0 -159
- package/project-skills/tdd-guard/src/cli/tdd-guard.ts +0 -48
- package/project-skills/tdd-guard/src/config/Config.test.ts +0 -538
- package/project-skills/tdd-guard/src/config/Config.ts +0 -172
- package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.test.ts +0 -58
- package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.ts +0 -8
- package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.test.ts +0 -347
- package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.ts +0 -61
- package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.test.ts +0 -24
- package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.ts +0 -7
- package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.test.ts +0 -377
- package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.ts +0 -75
- package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.test.ts +0 -563
- package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.ts +0 -140
- package/project-skills/tdd-guard/src/contracts/types/ClientType.ts +0 -1
- package/project-skills/tdd-guard/src/contracts/types/ConfigOptions.ts +0 -12
- package/project-skills/tdd-guard/src/contracts/types/Context.ts +0 -16
- package/project-skills/tdd-guard/src/contracts/types/ModelClient.ts +0 -3
- package/project-skills/tdd-guard/src/contracts/types/ValidationResult.ts +0 -6
- package/project-skills/tdd-guard/src/guard/GuardManager.test.ts +0 -336
- package/project-skills/tdd-guard/src/guard/GuardManager.ts +0 -83
- package/project-skills/tdd-guard/src/hooks/HookEvents.test.ts +0 -107
- package/project-skills/tdd-guard/src/hooks/HookEvents.ts +0 -39
- package/project-skills/tdd-guard/src/hooks/fileTypeDetection.ts +0 -16
- package/project-skills/tdd-guard/src/hooks/postToolLint.test.ts +0 -327
- package/project-skills/tdd-guard/src/hooks/postToolLint.ts +0 -165
- package/project-skills/tdd-guard/src/hooks/processHookData.test.ts +0 -465
- package/project-skills/tdd-guard/src/hooks/processHookData.ts +0 -203
- package/project-skills/tdd-guard/src/hooks/sessionHandler.test.ts +0 -136
- package/project-skills/tdd-guard/src/hooks/sessionHandler.ts +0 -31
- package/project-skills/tdd-guard/src/hooks/userPromptHandler.test.ts +0 -131
- package/project-skills/tdd-guard/src/hooks/userPromptHandler.ts +0 -55
- package/project-skills/tdd-guard/src/index.ts +0 -19
- package/project-skills/tdd-guard/src/linters/Linter.ts +0 -5
- package/project-skills/tdd-guard/src/linters/eslint/ESLint.test.ts +0 -183
- package/project-skills/tdd-guard/src/linters/eslint/ESLint.ts +0 -82
- package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.test.ts +0 -170
- package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.ts +0 -148
- package/project-skills/tdd-guard/src/processors/index.ts +0 -1
- package/project-skills/tdd-guard/src/processors/lintProcessor.ts +0 -77
- package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.test.ts +0 -303
- package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.ts +0 -255
- package/project-skills/tdd-guard/src/providers/LinterProvider.test.ts +0 -43
- package/project-skills/tdd-guard/src/providers/LinterProvider.ts +0 -20
- package/project-skills/tdd-guard/src/providers/ModelClientProvider.test.ts +0 -68
- package/project-skills/tdd-guard/src/providers/ModelClientProvider.ts +0 -22
- package/project-skills/tdd-guard/src/storage/FileStorage.test.ts +0 -76
- package/project-skills/tdd-guard/src/storage/FileStorage.ts +0 -108
- package/project-skills/tdd-guard/src/storage/MemoryStorage.ts +0 -57
- package/project-skills/tdd-guard/src/storage/Storage.test.ts +0 -227
- package/project-skills/tdd-guard/src/storage/Storage.ts +0 -17
- package/project-skills/tdd-guard/src/validation/context/context.test.ts +0 -364
- package/project-skills/tdd-guard/src/validation/context/context.ts +0 -155
- package/project-skills/tdd-guard/src/validation/models/AnthropicApi.test.ts +0 -171
- package/project-skills/tdd-guard/src/validation/models/AnthropicApi.ts +0 -49
- package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.test.ts +0 -167
- package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.ts +0 -54
- package/project-skills/tdd-guard/src/validation/models/ClaudeCli.test.ts +0 -239
- package/project-skills/tdd-guard/src/validation/models/ClaudeCli.ts +0 -57
- package/project-skills/tdd-guard/src/validation/prompts/file-types.ts +0 -52
- package/project-skills/tdd-guard/src/validation/prompts/operations/edit.ts +0 -58
- package/project-skills/tdd-guard/src/validation/prompts/operations/multi-edit.ts +0 -54
- package/project-skills/tdd-guard/src/validation/prompts/operations/write.ts +0 -54
- package/project-skills/tdd-guard/src/validation/prompts/response.ts +0 -40
- package/project-skills/tdd-guard/src/validation/prompts/rules.ts +0 -51
- package/project-skills/tdd-guard/src/validation/prompts/system-prompt.ts +0 -10
- package/project-skills/tdd-guard/src/validation/prompts/tools/lint-results.ts +0 -15
- package/project-skills/tdd-guard/src/validation/prompts/tools/test-output.ts +0 -14
- package/project-skills/tdd-guard/src/validation/prompts/tools/todos.ts +0 -9
- package/project-skills/tdd-guard/src/validation/validator.test.ts +0 -268
- package/project-skills/tdd-guard/src/validation/validator.ts +0 -159
- package/project-skills/tdd-guard/test/artifacts/go/.golangci.yml +0 -6
- package/project-skills/tdd-guard/test/artifacts/go/with-issues/file-with-issues.go +0 -12
- package/project-skills/tdd-guard/test/artifacts/go/with-issues/go.mod +0 -3
- package/project-skills/tdd-guard/test/artifacts/go/without-issues/file-without-issues.go +0 -7
- package/project-skills/tdd-guard/test/artifacts/go/without-issues/go.mod +0 -3
- package/project-skills/tdd-guard/test/artifacts/javascript/eslint.config.js +0 -20
- package/project-skills/tdd-guard/test/artifacts/javascript/file-with-issues.js +0 -12
- package/project-skills/tdd-guard/test/artifacts/javascript/file-without-issues.js +0 -10
- package/project-skills/tdd-guard/test/hooks/fileTypeDetection.test.ts +0 -26
- package/project-skills/tdd-guard/test/hooks/processHookData.fileType.test.ts +0 -46
- package/project-skills/tdd-guard/test/hooks/processHookData.python.test.ts +0 -68
- package/project-skills/tdd-guard/test/integration/test-context.test.ts +0 -66
- package/project-skills/tdd-guard/test/integration/validator.core.test.ts +0 -96
- package/project-skills/tdd-guard/test/integration/validator.scenarios.test.ts +0 -497
- package/project-skills/tdd-guard/test/utils/assertions.ts +0 -29
- package/project-skills/tdd-guard/test/utils/factories/contextFactory.ts +0 -30
- package/project-skills/tdd-guard/test/utils/factories/editFactory.ts +0 -82
- package/project-skills/tdd-guard/test/utils/factories/helpers.test.ts +0 -46
- package/project-skills/tdd-guard/test/utils/factories/helpers.ts +0 -46
- package/project-skills/tdd-guard/test/utils/factories/lintFactory.ts +0 -352
- package/project-skills/tdd-guard/test/utils/factories/modelClientProviderFactory.ts +0 -21
- package/project-skills/tdd-guard/test/utils/factories/multiEditFactory.ts +0 -79
- package/project-skills/tdd-guard/test/utils/factories/operations.ts +0 -57
- package/project-skills/tdd-guard/test/utils/factories/reporterFactory.ts +0 -55
- package/project-skills/tdd-guard/test/utils/factories/scenarios/index.ts +0 -22
- package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/python.ts +0 -745
- package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/typescript.ts +0 -767
- package/project-skills/tdd-guard/test/utils/factories/scenarios/types.ts +0 -77
- package/project-skills/tdd-guard/test/utils/factories/scenarios/utils.ts +0 -15
- package/project-skills/tdd-guard/test/utils/factories/sessionStartFactory.ts +0 -36
- package/project-skills/tdd-guard/test/utils/factories/testDefaults.ts +0 -90
- package/project-skills/tdd-guard/test/utils/factories/testResultsFactory.ts +0 -234
- package/project-skills/tdd-guard/test/utils/factories/todoFactory.ts +0 -99
- package/project-skills/tdd-guard/test/utils/factories/userPromptSubmitFactory.ts +0 -39
- package/project-skills/tdd-guard/test/utils/factories/writeFactory.ts +0 -70
- package/project-skills/tdd-guard/test/utils/index.ts +0 -131
- package/project-skills/tdd-guard/tsconfig.build.json +0 -16
- package/project-skills/tdd-guard/tsconfig.eslint.json +0 -17
- package/project-skills/tdd-guard/tsconfig.json +0 -32
- package/project-skills/tdd-guard/tsconfig.node.json +0 -10
- package/project-skills/tdd-guard/vitest.config.ts +0 -85
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
-
import { GolangciLint, buildArgs } from './GolangciLint'
|
|
3
|
-
import { join } from 'path'
|
|
4
|
-
import { hasRules, issuesFromFile } from '../../../test/utils/assertions'
|
|
5
|
-
|
|
6
|
-
// Test artifacts directory - defined once for reuse
|
|
7
|
-
const artifactsDir = join(process.cwd(), 'test', 'artifacts', 'go')
|
|
8
|
-
const configPath = join(artifactsDir, '.golangci.yml')
|
|
9
|
-
const withIssuesDir = join(artifactsDir, 'with-issues')
|
|
10
|
-
const withoutIssuesDir = join(artifactsDir, 'without-issues')
|
|
11
|
-
|
|
12
|
-
describe('GolangciLint', () => {
|
|
13
|
-
let linter: GolangciLint
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
linter = new GolangciLint()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
describe('basic functionality', () => {
|
|
20
|
-
test('can be instantiated', () => {
|
|
21
|
-
expect(linter).toBeDefined()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test('implements Linter interface with lint method', async () => {
|
|
25
|
-
const result = await linter.lint([])
|
|
26
|
-
|
|
27
|
-
expect(result).toBeDefined()
|
|
28
|
-
expect(result.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test('returns the file paths that were passed in', async () => {
|
|
32
|
-
const filePaths = ['main.go', 'pkg/handler.go']
|
|
33
|
-
const result = await linter.lint(filePaths)
|
|
34
|
-
|
|
35
|
-
expect(result.files).toEqual(filePaths)
|
|
36
|
-
})
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
describe('linting behavior', () => {
|
|
40
|
-
let originalCwd: string
|
|
41
|
-
|
|
42
|
-
beforeEach(() => {
|
|
43
|
-
originalCwd = process.cwd()
|
|
44
|
-
process.chdir(withIssuesDir)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
afterEach(() => {
|
|
48
|
-
process.chdir(originalCwd)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('detects issues in file with lint problems', async () => {
|
|
52
|
-
const filePath = join(withIssuesDir, 'file-with-issues.go')
|
|
53
|
-
const result = await linter.lint([filePath], configPath)
|
|
54
|
-
|
|
55
|
-
expect(result.issues.length).toBeGreaterThan(0)
|
|
56
|
-
expect(result.errorCount).toBeGreaterThan(0)
|
|
57
|
-
|
|
58
|
-
// Check for specific rules that should be detected
|
|
59
|
-
const expectedRules = ['typecheck']
|
|
60
|
-
const ruleResults = hasRules(result.issues, expectedRules)
|
|
61
|
-
|
|
62
|
-
ruleResults.forEach((ruleExists) => {
|
|
63
|
-
expect(ruleExists).toBe(true)
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
test('returns specific golangci-lint message for undefined variable', async () => {
|
|
68
|
-
const filePath = join(withIssuesDir, 'file-with-issues.go')
|
|
69
|
-
const result = await linter.lint([filePath])
|
|
70
|
-
|
|
71
|
-
const undefinedVarIssue = result.issues.find((issue) =>
|
|
72
|
-
issue.message.includes('undefined: messag')
|
|
73
|
-
)
|
|
74
|
-
expect(undefinedVarIssue).toMatchObject({
|
|
75
|
-
rule: 'typecheck',
|
|
76
|
-
message: expect.stringContaining('undefined: messag'),
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
test('returns no issues for clean Go file', async () => {
|
|
81
|
-
const filePath = join(withoutIssuesDir, 'file-without-issues.go')
|
|
82
|
-
const result = await linter.lint([filePath])
|
|
83
|
-
|
|
84
|
-
expect(result.issues.length).toBe(0)
|
|
85
|
-
expect(result.errorCount).toBe(0)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
test('returns exactly 2 issues for problematic file', async () => {
|
|
89
|
-
const filePath = join(withIssuesDir, 'file-with-issues.go')
|
|
90
|
-
const result = await linter.lint([filePath])
|
|
91
|
-
|
|
92
|
-
expect(result.issues.length).toBe(2)
|
|
93
|
-
expect(result.errorCount).toBe(2)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
test('returns different results for different files', async () => {
|
|
97
|
-
const problemFile = join(withIssuesDir, 'file-with-issues.go')
|
|
98
|
-
const cleanFile = join(withoutIssuesDir, 'file-without-issues.go')
|
|
99
|
-
|
|
100
|
-
const problemResult = await linter.lint([problemFile])
|
|
101
|
-
const cleanResult = await linter.lint([cleanFile])
|
|
102
|
-
|
|
103
|
-
expect(problemResult.issues.length).toBeGreaterThan(0)
|
|
104
|
-
expect(cleanResult.issues.length).toBe(0)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
test('processes individual files correctly', async () => {
|
|
108
|
-
const problemFile = join(withIssuesDir, 'file-with-issues.go')
|
|
109
|
-
const result = await linter.lint([problemFile])
|
|
110
|
-
|
|
111
|
-
expect(result.files).toEqual([problemFile])
|
|
112
|
-
expect(result.issues.length).toBeGreaterThan(0)
|
|
113
|
-
|
|
114
|
-
// All issues should be from the problematic file
|
|
115
|
-
const problemFileIssues = issuesFromFile(
|
|
116
|
-
result.issues,
|
|
117
|
-
'file-with-issues.go'
|
|
118
|
-
)
|
|
119
|
-
expect(problemFileIssues.length).toBeGreaterThan(0)
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
describe('directory-based linting', () => {
|
|
124
|
-
test('should build args for directory-based linting with current directory', () => {
|
|
125
|
-
const args = buildArgs([], configPath)
|
|
126
|
-
|
|
127
|
-
// Should contain basic golangci-lint arguments
|
|
128
|
-
expect(args).toContain('run')
|
|
129
|
-
expect(args).toContain('--output.json.path=stdout')
|
|
130
|
-
expect(args).toContain('--config')
|
|
131
|
-
expect(args).toContain(configPath)
|
|
132
|
-
|
|
133
|
-
// With empty filePaths, should have no directories in args
|
|
134
|
-
expect(args).not.toContain('.')
|
|
135
|
-
expect(args).toContain('--path-mode=abs')
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe('with files containing special characters', () => {
|
|
140
|
-
test.each([
|
|
141
|
-
['spaces', 'src/my file with spaces.go'],
|
|
142
|
-
['quotes', 'src/file"with"quotes.go'],
|
|
143
|
-
['semicolons', 'src/file;name.go'],
|
|
144
|
-
['backticks', 'src/file`with`backticks.go'],
|
|
145
|
-
['dollar signs', 'src/file$with$dollar.go'],
|
|
146
|
-
['pipes', 'src/file|with|pipes.go'],
|
|
147
|
-
['ampersands', 'src/file&with&ersands.go'],
|
|
148
|
-
['parentheses', 'src/file(with)parentheses.go'],
|
|
149
|
-
['command injection attempt', 'file.go"; cat /etc/passwd; echo "'],
|
|
150
|
-
['newlines', 'src/file\nwith\nnewlines.go'],
|
|
151
|
-
['tabs', 'src/file\twith\ttabs.go'],
|
|
152
|
-
])('handles file paths with %s correctly', async (_, filePath) => {
|
|
153
|
-
const result = await linter.lint([filePath])
|
|
154
|
-
|
|
155
|
-
expect(result.files).toEqual([filePath])
|
|
156
|
-
expect(result.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
test.each([
|
|
160
|
-
['spaces', '/path with spaces/.golangci.yml'],
|
|
161
|
-
['quotes', '/path"with"quotes/.golangci.yml'],
|
|
162
|
-
['special chars', '/path;with&special|chars/.golangci.yml'],
|
|
163
|
-
])('handles config paths with %s correctly', async (_, configFilePath) => {
|
|
164
|
-
const result = await linter.lint(['main.go'], configFilePath)
|
|
165
|
-
|
|
166
|
-
expect(result.files).toEqual(['main.go'])
|
|
167
|
-
expect(result.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
})
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LintResult,
|
|
3
|
-
LintIssue,
|
|
4
|
-
GolangciLintIssue,
|
|
5
|
-
GolangciLintResult,
|
|
6
|
-
} from '../../contracts/schemas/lintSchemas'
|
|
7
|
-
import { execFile } from 'child_process'
|
|
8
|
-
import { promisify } from 'util'
|
|
9
|
-
import { dirname } from 'path'
|
|
10
|
-
import { Linter } from '../Linter'
|
|
11
|
-
|
|
12
|
-
const execFileAsync = promisify(execFile)
|
|
13
|
-
|
|
14
|
-
export class GolangciLint implements Linter {
|
|
15
|
-
async lint(filePaths: string[], configPath?: string): Promise<LintResult> {
|
|
16
|
-
const timestamp = new Date().toISOString()
|
|
17
|
-
const args = buildArgs(filePaths, configPath)
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
// golangci-lint exits with non-zero code when issues are found
|
|
21
|
-
await execFileAsync('golangci-lint', args)
|
|
22
|
-
return createLintData(timestamp, filePaths, [])
|
|
23
|
-
} catch (error) {
|
|
24
|
-
if (!isExecError(error)) throw error
|
|
25
|
-
|
|
26
|
-
const results = parseResults(error.stdout)
|
|
27
|
-
return createLintData(timestamp, filePaths, results)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Helper functions
|
|
33
|
-
export const buildArgs = (
|
|
34
|
-
filePaths: string[],
|
|
35
|
-
configPath?: string
|
|
36
|
-
): string[] => {
|
|
37
|
-
const args = ['run', '--output.json.path=stdout', '--path-mode=abs']
|
|
38
|
-
|
|
39
|
-
if (configPath) {
|
|
40
|
-
args.push('--config', configPath)
|
|
41
|
-
} else {
|
|
42
|
-
args.push('--no-config')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Convert file paths to unique directories since golangci-lint runs on directories
|
|
46
|
-
const directories = [...new Set(filePaths.map((file) => dirname(file)))]
|
|
47
|
-
args.push(...directories)
|
|
48
|
-
|
|
49
|
-
return args
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const isExecError = (error: unknown): error is Error & { stdout?: string } =>
|
|
53
|
-
error !== null && typeof error === 'object' && 'stdout' in error
|
|
54
|
-
|
|
55
|
-
// Parse golangci-lint JSON output - only first line contains JSON, rest is summary
|
|
56
|
-
const parseResults = (stdout?: string): GolangciLintIssue[] => {
|
|
57
|
-
try {
|
|
58
|
-
if (stdout === undefined || stdout === '') {
|
|
59
|
-
return []
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const lines = stdout.split('\n')
|
|
63
|
-
const jsonLine = lines[0]
|
|
64
|
-
if (jsonLine.trim() === '') {
|
|
65
|
-
return []
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const parsed: GolangciLintResult = JSON.parse(jsonLine)
|
|
69
|
-
return parsed.Issues ?? []
|
|
70
|
-
} catch {
|
|
71
|
-
return []
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const createLintData = (
|
|
76
|
-
timestamp: string,
|
|
77
|
-
files: string[],
|
|
78
|
-
results: GolangciLintIssue[]
|
|
79
|
-
): LintResult => {
|
|
80
|
-
const issues = results.flatMap(toIssue)
|
|
81
|
-
return {
|
|
82
|
-
timestamp,
|
|
83
|
-
files,
|
|
84
|
-
issues,
|
|
85
|
-
errorCount: countBySeverity(issues, 'error'),
|
|
86
|
-
warningCount: countBySeverity(issues, 'warning'),
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const toIssue = (issue: GolangciLintIssue): LintIssue[] => {
|
|
91
|
-
// Check if this contains multiple issues in the Text field
|
|
92
|
-
if (issue.Text.includes('\n') && issue.Text.includes('.go:')) {
|
|
93
|
-
// Parse multi-line text to extract individual issues
|
|
94
|
-
const lines = issue.Text.split('\n').slice(1) // Skip module name line
|
|
95
|
-
return lines
|
|
96
|
-
.filter((line) => line.includes('.go:'))
|
|
97
|
-
.map((line) => parseIssueLine(line, issue.FromLinter))
|
|
98
|
-
.filter((parsedIssue): parsedIssue is LintIssue => parsedIssue !== null)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Single issue
|
|
102
|
-
return [
|
|
103
|
-
{
|
|
104
|
-
file: issue.Pos.Filename,
|
|
105
|
-
line: issue.Pos.Line,
|
|
106
|
-
column: issue.Pos.Column,
|
|
107
|
-
severity: 'error' as const,
|
|
108
|
-
message: issue.Text,
|
|
109
|
-
rule: issue.FromLinter,
|
|
110
|
-
},
|
|
111
|
-
]
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const parseIssueLine = (line: string, linter: string): LintIssue | null => {
|
|
115
|
-
// Parse format: "./file-with-issues.go:8:2: declared and not used: message"
|
|
116
|
-
const parts = line.split(':')
|
|
117
|
-
const MIN_PARTS = 4 // filename:line:column:message
|
|
118
|
-
|
|
119
|
-
if (parts.length < MIN_PARTS || !line.includes('.go:')) return null
|
|
120
|
-
|
|
121
|
-
const filename = parts[0]
|
|
122
|
-
const lineStr = parts[1]
|
|
123
|
-
const columnStr = parts[2]
|
|
124
|
-
const MESSAGE_START_INDEX = 3
|
|
125
|
-
const message = parts.slice(MESSAGE_START_INDEX).join(':').trim()
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
!filename.endsWith('.go') ||
|
|
129
|
-
!/^\d+$/.test(lineStr) ||
|
|
130
|
-
!/^\d+$/.test(columnStr)
|
|
131
|
-
) {
|
|
132
|
-
return null
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
file: filename,
|
|
137
|
-
line: parseInt(lineStr, 10),
|
|
138
|
-
column: parseInt(columnStr, 10),
|
|
139
|
-
severity: 'error' as const,
|
|
140
|
-
message,
|
|
141
|
-
rule: linter,
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const countBySeverity = (
|
|
146
|
-
issues: LintIssue[],
|
|
147
|
-
severity: 'error' | 'warning'
|
|
148
|
-
): number => issues.filter((i) => i.severity === severity).length
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { TestResultsProcessor } from './testResults/TestResultsProcessor'
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { ProcessedLintData } from '../contracts/types/Context'
|
|
2
|
-
import { LintData } from '../contracts/schemas/lintSchemas'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Processes lint data into a presentable format for validation context
|
|
6
|
-
*/
|
|
7
|
-
export function processLintData(lintData?: LintData): ProcessedLintData {
|
|
8
|
-
if (!lintData) {
|
|
9
|
-
return {
|
|
10
|
-
hasIssues: false,
|
|
11
|
-
summary: 'No lint data available',
|
|
12
|
-
issuesByFile: new Map(),
|
|
13
|
-
totalIssues: 0,
|
|
14
|
-
errorCount: 0,
|
|
15
|
-
warningCount: 0,
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const hasIssues = lintData.errorCount > 0 || lintData.warningCount > 0
|
|
20
|
-
const totalIssues = lintData.errorCount + lintData.warningCount
|
|
21
|
-
|
|
22
|
-
if (!hasIssues) {
|
|
23
|
-
return {
|
|
24
|
-
hasIssues: false,
|
|
25
|
-
summary: 'No lint issues found',
|
|
26
|
-
issuesByFile: new Map(),
|
|
27
|
-
totalIssues: 0,
|
|
28
|
-
errorCount: 0,
|
|
29
|
-
warningCount: 0,
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Group issues by file
|
|
34
|
-
const issuesByFile = new Map<string, string[]>()
|
|
35
|
-
for (const issue of lintData.issues) {
|
|
36
|
-
if (!issuesByFile.has(issue.file)) {
|
|
37
|
-
issuesByFile.set(issue.file, [])
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const ruleInfo = issue.rule ? ` (${issue.rule})` : ''
|
|
41
|
-
const formattedIssue = ` Line ${issue.line}:${issue.column} - ${issue.severity}: ${issue.message}${ruleInfo}`
|
|
42
|
-
issuesByFile.get(issue.file)!.push(formattedIssue)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const summary = `${totalIssues} lint ${totalIssues === 1 ? 'issue' : 'issues'} found (${lintData.errorCount} ${lintData.errorCount === 1 ? 'error' : 'errors'}, ${lintData.warningCount} ${lintData.warningCount === 1 ? 'warning' : 'warnings'})`
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
hasIssues: true,
|
|
49
|
-
summary,
|
|
50
|
-
issuesByFile,
|
|
51
|
-
totalIssues,
|
|
52
|
-
errorCount: lintData.errorCount,
|
|
53
|
-
warningCount: lintData.warningCount,
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Formats processed lint data as a readable string for AI context
|
|
59
|
-
*/
|
|
60
|
-
export function formatLintDataForContext(
|
|
61
|
-
processedLint: ProcessedLintData
|
|
62
|
-
): string {
|
|
63
|
-
if (!processedLint.hasIssues) {
|
|
64
|
-
return processedLint.summary
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
let formatted = `Code Quality Status: ${processedLint.summary}\n`
|
|
68
|
-
|
|
69
|
-
if (processedLint.issuesByFile.size > 0) {
|
|
70
|
-
formatted += '\nLint Issues by File:\n'
|
|
71
|
-
for (const [file, issues] of processedLint.issuesByFile) {
|
|
72
|
-
formatted += `\n${file}:\n${issues.join('\n')}\n`
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return formatted.trim()
|
|
77
|
-
}
|
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
-
import { TestResultsProcessor } from './TestResultsProcessor'
|
|
3
|
-
import { testData } from '../../../test/utils'
|
|
4
|
-
|
|
5
|
-
describe('TestResultsProcessor', () => {
|
|
6
|
-
it('should format empty test results', () => {
|
|
7
|
-
const processor = new TestResultsProcessor()
|
|
8
|
-
const result = processor.process('{}')
|
|
9
|
-
|
|
10
|
-
expect(result).toBe('No test results found.')
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('should handle invalid JSON gracefully', () => {
|
|
14
|
-
const processor = new TestResultsProcessor()
|
|
15
|
-
const result = processor.process('invalid json')
|
|
16
|
-
|
|
17
|
-
expect(result).toBe('Invalid JSON format.')
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('should handle invalid test result format', () => {
|
|
21
|
-
const processor = new TestResultsProcessor()
|
|
22
|
-
const result = processor.process('{"testModules": "not an array"}')
|
|
23
|
-
|
|
24
|
-
expect(result).toBe('Invalid test result format.')
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
describe('scenarios', () => {
|
|
28
|
-
it('should format all error messages for a failing test', () => {
|
|
29
|
-
const processor = new TestResultsProcessor()
|
|
30
|
-
const testResults = {
|
|
31
|
-
testModules: [
|
|
32
|
-
{
|
|
33
|
-
moduleId: '/src/example.test.ts',
|
|
34
|
-
tests: [
|
|
35
|
-
{
|
|
36
|
-
name: 'CompilationError',
|
|
37
|
-
fullName: 'CompilationError',
|
|
38
|
-
state: 'failed',
|
|
39
|
-
errors: [
|
|
40
|
-
{ message: 'example.go:9:8: undefined: NewFormatter' },
|
|
41
|
-
{ message: 'example.go:10:12: undefined: TestEvent' },
|
|
42
|
-
{ message: 'example.go:11:5: undefined: SomeOtherThing' },
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
reason: 'failed',
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
52
|
-
|
|
53
|
-
// Check that key elements are present
|
|
54
|
-
expect(result).toContain('/src/example.test.ts')
|
|
55
|
-
expect(result).toContain('CompilationError')
|
|
56
|
-
expect(result).toContain('example.go')
|
|
57
|
-
expect(result).toContain('undefined: NewFormatter')
|
|
58
|
-
expect(result).toContain('undefined: TestEvent')
|
|
59
|
-
expect(result).toContain('undefined: SomeOtherThing')
|
|
60
|
-
|
|
61
|
-
// Check summary
|
|
62
|
-
expect(result).toContain('Test Files')
|
|
63
|
-
expect(result).toContain('1 failed')
|
|
64
|
-
expect(result).toContain('Tests')
|
|
65
|
-
expect(result).toContain('1 failed')
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('2 passing tests in the same file', () => {
|
|
69
|
-
const processor = new TestResultsProcessor()
|
|
70
|
-
const testResults = testData.passingTestResults()
|
|
71
|
-
|
|
72
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
73
|
-
|
|
74
|
-
const expected = ` ✓ /src/example.test.ts (2 tests) 0ms
|
|
75
|
-
|
|
76
|
-
Test Files 1 passed (1)
|
|
77
|
-
Tests 2 passed (2)
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
expect(result).toBe(expected)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('2 failing tests in the same file', () => {
|
|
84
|
-
const processor = new TestResultsProcessor()
|
|
85
|
-
const testResults = testData.multipleFailedTestResults()
|
|
86
|
-
|
|
87
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
88
|
-
|
|
89
|
-
const expected = ` ❯ /src/calculator.test.ts (2 tests | 2 failed) 0ms
|
|
90
|
-
× Calculator > should add two numbers 0ms
|
|
91
|
-
→ expected 5 to be 6
|
|
92
|
-
× Calculator > should multiply two numbers 0ms
|
|
93
|
-
→ expected 12 to be 15
|
|
94
|
-
|
|
95
|
-
Test Files 1 failed (1)
|
|
96
|
-
Tests 2 failed (2)
|
|
97
|
-
`
|
|
98
|
-
|
|
99
|
-
expect(result).toBe(expected)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('1 passing and 1 failing test in the same file', () => {
|
|
103
|
-
const processor = new TestResultsProcessor()
|
|
104
|
-
const testResults = testData.mixedTestResults()
|
|
105
|
-
|
|
106
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
107
|
-
|
|
108
|
-
const expected = ` ❯ /src/calculator.test.ts (2 tests | 1 failed) 0ms
|
|
109
|
-
✓ Calculator > should add two numbers 0ms
|
|
110
|
-
× Calculator > should multiply two numbers 0ms
|
|
111
|
-
→ expected 12 to be 15
|
|
112
|
-
|
|
113
|
-
Test Files 1 failed | 0 passed (1)
|
|
114
|
-
Tests 1 failed | 1 passed (2)
|
|
115
|
-
`
|
|
116
|
-
|
|
117
|
-
expect(result).toBe(expected)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('2 files with a passing and a failing test pair in each', () => {
|
|
121
|
-
const processor = new TestResultsProcessor()
|
|
122
|
-
const testResults = testData.multipleModulesTestResults()
|
|
123
|
-
|
|
124
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
125
|
-
|
|
126
|
-
const expected = ` ❯ /src/calculator.test.ts (2 tests | 1 failed) 0ms
|
|
127
|
-
✓ Calculator > should add two numbers 0ms
|
|
128
|
-
× Calculator > should multiply two numbers 0ms
|
|
129
|
-
→ expected 12 to be 15
|
|
130
|
-
❯ /src/utils/formatter.test.ts (2 tests | 1 failed) 0ms
|
|
131
|
-
✓ Formatter > should format currency 0ms
|
|
132
|
-
× Formatter > should format date 0ms
|
|
133
|
-
→ expected "2024-01-01" to be "01/01/2024"
|
|
134
|
-
|
|
135
|
-
Test Files 2 failed | 0 passed (2)
|
|
136
|
-
Tests 2 failed | 2 passed (4)
|
|
137
|
-
`
|
|
138
|
-
|
|
139
|
-
expect(result).toBe(expected)
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
it('should handle pytest format with passing tests', () => {
|
|
144
|
-
const processor = new TestResultsProcessor()
|
|
145
|
-
const pytestResults = {
|
|
146
|
-
testModules: [
|
|
147
|
-
{
|
|
148
|
-
moduleId: 'test_example.py',
|
|
149
|
-
tests: [
|
|
150
|
-
{
|
|
151
|
-
name: 'test_addition',
|
|
152
|
-
fullName: 'test_example.py::test_addition',
|
|
153
|
-
state: 'passed',
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
},
|
|
157
|
-
],
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const result = processor.process(JSON.stringify(pytestResults))
|
|
161
|
-
|
|
162
|
-
const expected = ` ✓ test_example.py (1 tests) 0ms
|
|
163
|
-
|
|
164
|
-
Test Files 1 passed (1)
|
|
165
|
-
Tests 1 passed (1)
|
|
166
|
-
`
|
|
167
|
-
|
|
168
|
-
expect(result).toBe(expected)
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
describe('formats unhandled errors separately from test results', () => {
|
|
172
|
-
let processor: TestResultsProcessor
|
|
173
|
-
let result: string
|
|
174
|
-
|
|
175
|
-
beforeEach(() => {
|
|
176
|
-
processor = new TestResultsProcessor()
|
|
177
|
-
const testResults = testData.createTestResults({
|
|
178
|
-
testModules: [testData.createTestModule()],
|
|
179
|
-
unhandledErrors: [testData.createUnhandledError()],
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
result = processor.process(JSON.stringify(testResults))
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
it('shows module as passed with 0 tests', () => {
|
|
186
|
-
expect(result).toContain('✓ /src/example.test.ts (0 tests)')
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
it('displays unhandled errors section', () => {
|
|
190
|
-
expect(result).toContain('Unhandled Errors:')
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
it('shows error name and message', () => {
|
|
194
|
-
expect(result).toContain('× Error: Cannot find module "./helpers"')
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('includes stack trace', () => {
|
|
198
|
-
expect(result).toContain('Stack:')
|
|
199
|
-
expect(result).toContain('imported from')
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('summary shows passed test file', () => {
|
|
203
|
-
expect(result).toContain('Test Files 1 passed (1)')
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
it('summary shows 0 tests', () => {
|
|
207
|
-
expect(result).toContain('Tests 0 passed (0)')
|
|
208
|
-
})
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
describe('handles test run end reason', () => {
|
|
212
|
-
it('displays reason explanation when test run failed with import error', () => {
|
|
213
|
-
const processor = new TestResultsProcessor()
|
|
214
|
-
const testResults = testData.createTestResults({
|
|
215
|
-
testModules: [testData.createTestModule()],
|
|
216
|
-
unhandledErrors: [testData.createUnhandledError()],
|
|
217
|
-
reason: 'failed',
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
221
|
-
|
|
222
|
-
expect(result).toContain(
|
|
223
|
-
'Test run failed - This is likely when an imported module can not be found'
|
|
224
|
-
)
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
it('does not display import error explanation when tests fail for other reasons', () => {
|
|
228
|
-
const processor = new TestResultsProcessor()
|
|
229
|
-
const testResults = testData.createTestResults({
|
|
230
|
-
testModules: [
|
|
231
|
-
testData.createTestModule({
|
|
232
|
-
moduleId: '/src/calculator.test.ts',
|
|
233
|
-
tests: [
|
|
234
|
-
testData.createTest({
|
|
235
|
-
name: 'should add two numbers',
|
|
236
|
-
fullName: 'Calculator > should add two numbers',
|
|
237
|
-
state: 'failed',
|
|
238
|
-
errors: [
|
|
239
|
-
testData.createTestError({
|
|
240
|
-
message: 'expected 5 to be 6',
|
|
241
|
-
}),
|
|
242
|
-
],
|
|
243
|
-
}),
|
|
244
|
-
],
|
|
245
|
-
}),
|
|
246
|
-
],
|
|
247
|
-
unhandledErrors: [],
|
|
248
|
-
reason: 'failed',
|
|
249
|
-
})
|
|
250
|
-
|
|
251
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
252
|
-
|
|
253
|
-
expect(result).not.toContain(
|
|
254
|
-
'This is likely when an imported module can not be found'
|
|
255
|
-
)
|
|
256
|
-
expect(result).toContain('expected 5 to be 6')
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
it('displays reason explanation when test run failed with no tests collected', () => {
|
|
260
|
-
const processor = new TestResultsProcessor()
|
|
261
|
-
const testResults = testData.createTestResults({
|
|
262
|
-
testModules: [testData.createTestModule()],
|
|
263
|
-
reason: 'failed',
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
267
|
-
|
|
268
|
-
expect(result).toContain(
|
|
269
|
-
'Test run failed - This is likely when an imported module can not be found'
|
|
270
|
-
)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
it('shows module as failed when test run failed with no tests', () => {
|
|
274
|
-
const processor = new TestResultsProcessor()
|
|
275
|
-
const testResults = testData.createTestResults({
|
|
276
|
-
testModules: [
|
|
277
|
-
testData.createTestModule({
|
|
278
|
-
moduleId: '/src/linters/eslint/helpers.test.ts',
|
|
279
|
-
}),
|
|
280
|
-
],
|
|
281
|
-
reason: 'failed',
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
285
|
-
|
|
286
|
-
expect(result).toContain(
|
|
287
|
-
'❯ /src/linters/eslint/helpers.test.ts (0 tests | 0 failed) 0ms'
|
|
288
|
-
)
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
it('counts module as failed in summary when test run failed with no tests', () => {
|
|
292
|
-
const processor = new TestResultsProcessor()
|
|
293
|
-
const testResults = testData.createTestResults({
|
|
294
|
-
testModules: [testData.createTestModule()],
|
|
295
|
-
reason: 'failed',
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
const result = processor.process(JSON.stringify(testResults))
|
|
299
|
-
|
|
300
|
-
expect(result).toContain('Test Files 1 failed (1)')
|
|
301
|
-
})
|
|
302
|
-
})
|
|
303
|
-
})
|