@sk8metal/michi-cli 0.4.0 → 0.7.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/CHANGELOG.md +162 -1
- package/README.md +2 -1
- package/dist/scripts/config/config-schema.d.ts +87 -0
- package/dist/scripts/config/config-schema.d.ts.map +1 -1
- package/dist/scripts/config/config-schema.js +81 -0
- package/dist/scripts/config/config-schema.js.map +1 -1
- package/dist/scripts/confluence-sync.d.ts.map +1 -1
- package/dist/scripts/confluence-sync.js +15 -2
- package/dist/scripts/confluence-sync.js.map +1 -1
- package/dist/scripts/github-actions-client.d.ts +79 -0
- package/dist/scripts/github-actions-client.d.ts.map +1 -0
- package/dist/scripts/github-actions-client.js +182 -0
- package/dist/scripts/github-actions-client.js.map +1 -0
- package/dist/scripts/health-check-service.d.ts +46 -0
- package/dist/scripts/health-check-service.d.ts.map +1 -0
- package/dist/scripts/health-check-service.js +114 -0
- package/dist/scripts/health-check-service.js.map +1 -0
- package/dist/scripts/markdown-to-confluence.d.ts.map +1 -1
- package/dist/scripts/markdown-to-confluence.js +25 -3
- package/dist/scripts/markdown-to-confluence.js.map +1 -1
- package/dist/scripts/mermaid-converter.d.ts +24 -0
- package/dist/scripts/mermaid-converter.d.ts.map +1 -0
- package/dist/scripts/mermaid-converter.js +49 -0
- package/dist/scripts/mermaid-converter.js.map +1 -0
- package/dist/scripts/pr-automation.d.ts.map +1 -1
- package/dist/scripts/pr-automation.js +11 -3
- package/dist/scripts/pr-automation.js.map +1 -1
- package/dist/scripts/spec-impl-workflow.d.ts.map +1 -1
- package/dist/scripts/spec-impl-workflow.js +22 -6
- package/dist/scripts/spec-impl-workflow.js.map +1 -1
- package/dist/scripts/template/multi-repo-renderer.d.ts +67 -0
- package/dist/scripts/template/multi-repo-renderer.d.ts.map +1 -0
- package/dist/scripts/template/multi-repo-renderer.js +123 -0
- package/dist/scripts/template/multi-repo-renderer.js.map +1 -0
- package/dist/scripts/template/renderer.d.ts +4 -0
- package/dist/scripts/template/renderer.d.ts.map +1 -1
- package/dist/scripts/template/renderer.js.map +1 -1
- package/dist/scripts/test-execution-generator.d.ts.map +1 -1
- package/dist/scripts/test-execution-generator.js +94 -11
- package/dist/scripts/test-execution-generator.js.map +1 -1
- package/dist/scripts/test-script-runner.d.ts +33 -0
- package/dist/scripts/test-script-runner.d.ts.map +1 -0
- package/dist/scripts/test-script-runner.js +77 -0
- package/dist/scripts/test-script-runner.js.map +1 -0
- package/dist/scripts/utils/config-loader.d.ts +31 -5
- package/dist/scripts/utils/config-loader.d.ts.map +1 -1
- package/dist/scripts/utils/config-loader.js +363 -50
- package/dist/scripts/utils/config-loader.js.map +1 -1
- package/dist/scripts/utils/env-config.d.ts +1 -1
- package/dist/scripts/utils/env-config.d.ts.map +1 -1
- package/dist/scripts/utils/env-config.js +2 -14
- package/dist/scripts/utils/env-config.js.map +1 -1
- package/dist/scripts/utils/multi-repo-validator.d.ts +30 -0
- package/dist/scripts/utils/multi-repo-validator.d.ts.map +1 -0
- package/dist/scripts/utils/multi-repo-validator.js +105 -0
- package/dist/scripts/utils/multi-repo-validator.js.map +1 -0
- package/dist/scripts/utils/project-meta.d.ts +9 -0
- package/dist/scripts/utils/project-meta.d.ts.map +1 -1
- package/dist/scripts/utils/project-meta.js +22 -0
- package/dist/scripts/utils/project-meta.js.map +1 -1
- package/dist/scripts/utils/security-validator.d.ts +55 -0
- package/dist/scripts/utils/security-validator.d.ts.map +1 -0
- package/dist/scripts/utils/security-validator.js +232 -0
- package/dist/scripts/utils/security-validator.js.map +1 -0
- package/dist/scripts/utils/spec-archiver.d.ts +38 -0
- package/dist/scripts/utils/spec-archiver.d.ts.map +1 -0
- package/dist/scripts/utils/spec-archiver.js +210 -0
- package/dist/scripts/utils/spec-archiver.js.map +1 -0
- package/dist/scripts/utils/spec-updater.d.ts +4 -0
- package/dist/scripts/utils/spec-updater.d.ts.map +1 -1
- package/dist/scripts/utils/spec-updater.js.map +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +303 -17
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/config-validate.d.ts +9 -0
- package/dist/src/commands/config-validate.d.ts.map +1 -0
- package/dist/src/commands/config-validate.js +90 -0
- package/dist/src/commands/config-validate.js.map +1 -0
- package/dist/src/commands/init.d.ts +1 -0
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +29 -6
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/migrate.d.ts +25 -0
- package/dist/src/commands/migrate.d.ts.map +1 -0
- package/dist/src/commands/migrate.js +341 -0
- package/dist/src/commands/migrate.js.map +1 -0
- package/dist/src/commands/multi-repo-add-repo.d.ts +26 -0
- package/dist/src/commands/multi-repo-add-repo.d.ts.map +1 -0
- package/dist/src/commands/multi-repo-add-repo.js +56 -0
- package/dist/src/commands/multi-repo-add-repo.js.map +1 -0
- package/dist/src/commands/multi-repo-ci-status.d.ts +46 -0
- package/dist/src/commands/multi-repo-ci-status.d.ts.map +1 -0
- package/dist/src/commands/multi-repo-ci-status.js +285 -0
- package/dist/src/commands/multi-repo-ci-status.js.map +1 -0
- package/dist/src/commands/multi-repo-confluence-sync.d.ts +45 -0
- package/dist/src/commands/multi-repo-confluence-sync.d.ts.map +1 -0
- package/dist/src/commands/multi-repo-confluence-sync.js +135 -0
- package/dist/src/commands/multi-repo-confluence-sync.js.map +1 -0
- package/dist/src/commands/multi-repo-init.d.ts +26 -0
- package/dist/src/commands/multi-repo-init.d.ts.map +1 -0
- package/dist/src/commands/multi-repo-init.js +101 -0
- package/dist/src/commands/multi-repo-init.js.map +1 -0
- package/dist/src/commands/multi-repo-list.d.ts +28 -0
- package/dist/src/commands/multi-repo-list.d.ts.map +1 -0
- package/dist/src/commands/multi-repo-list.js +38 -0
- package/dist/src/commands/multi-repo-list.js.map +1 -0
- package/dist/src/commands/multi-repo-test.d.ts +56 -0
- package/dist/src/commands/multi-repo-test.d.ts.map +1 -0
- package/dist/src/commands/multi-repo-test.js +70 -0
- package/dist/src/commands/multi-repo-test.js.map +1 -0
- package/dist/src/commands/setup-existing.d.ts.map +1 -1
- package/dist/src/commands/setup-existing.js +0 -1
- package/dist/src/commands/setup-existing.js.map +1 -1
- package/dist/src/commands/spec-archive.d.ts +17 -0
- package/dist/src/commands/spec-archive.d.ts.map +1 -0
- package/dist/src/commands/spec-archive.js +40 -0
- package/dist/src/commands/spec-archive.js.map +1 -0
- package/dist/src/commands/spec-list.d.ts +15 -0
- package/dist/src/commands/spec-list.d.ts.map +1 -0
- package/dist/src/commands/spec-list.js +55 -0
- package/dist/src/commands/spec-list.js.map +1 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +32 -8
- package/dist/vitest.config.js.map +1 -1
- package/docs/michi-development/design/config-unification.md +4789 -0
- package/docs/user-guide/getting-started/github-token-setup.md +2 -1
- package/docs/user-guide/getting-started/new-repository-setup.md +1 -1
- package/docs/user-guide/getting-started/quick-start.md +1 -1
- package/docs/user-guide/getting-started/setup.md +4 -11
- package/docs/user-guide/guides/multi-repo-guide.md +591 -0
- package/docs/user-guide/guides/multi-repo-migration-guide.md +516 -0
- package/docs/user-guide/hands-on/claude-agent-setup.md +2 -2
- package/docs/user-guide/hands-on/claude-setup.md +2 -2
- package/docs/user-guide/hands-on/cursor-setup.md +2 -2
- package/docs/user-guide/hands-on/workflow-walkthrough.md +4 -1
- package/docs/user-guide/reference/multi-repo-api.md +771 -0
- package/docs/user-guide/reference/quick-reference.md +22 -37
- package/env.example +1 -1
- package/package.json +2 -5
- package/scripts/__tests__/config-loader-multi-repo.test.ts +342 -0
- package/scripts/__tests__/github-actions-client.test.ts +543 -0
- package/scripts/__tests__/health-check-service.test.ts +142 -0
- package/scripts/__tests__/markdown-to-confluence.test.ts +262 -0
- package/scripts/__tests__/mermaid-converter.test.ts +236 -0
- package/scripts/__tests__/multi-repo-config-schema.test.ts +335 -0
- package/scripts/__tests__/multi-repo-validator.test.ts +524 -0
- package/scripts/__tests__/spec-archiver.test.ts +512 -0
- package/scripts/__tests__/spec-impl-workflow.test.ts +5 -2
- package/scripts/__tests__/test-script-runner.test.ts +217 -0
- package/scripts/config/config-schema.ts +104 -0
- package/scripts/confluence-sync.ts +16 -2
- package/scripts/github-actions-client.ts +258 -0
- package/scripts/health-check-service.ts +171 -0
- package/scripts/markdown-to-confluence.ts +37 -6
- package/scripts/mermaid-converter.ts +56 -0
- package/scripts/pr-automation.ts +15 -5
- package/scripts/spec-impl-workflow.ts +22 -6
- package/scripts/template/__tests__/multi-repo-renderer.test.ts +261 -0
- package/scripts/template/multi-repo-renderer.ts +172 -0
- package/scripts/template/renderer.ts +5 -0
- package/scripts/test-execution-generator.ts +104 -11
- package/scripts/test-script-runner.ts +130 -0
- package/scripts/utils/__tests__/config-loader.test.ts +149 -0
- package/scripts/utils/__tests__/config-validator.test.ts +106 -6
- package/scripts/utils/__tests__/env-config.test.ts +0 -2
- package/scripts/utils/__tests__/multi-repo-validator.test.ts +335 -0
- package/scripts/utils/__tests__/project-meta.test.ts +192 -0
- package/scripts/utils/__tests__/security-validator.test.ts +272 -0
- package/scripts/utils/config-loader.ts +429 -56
- package/scripts/utils/env-config.ts +2 -14
- package/scripts/utils/multi-repo-validator.ts +141 -0
- package/scripts/utils/project-meta.ts +27 -0
- package/scripts/utils/security-validator.ts +286 -0
- package/scripts/utils/spec-archiver.ts +260 -0
- package/scripts/utils/spec-updater.ts +4 -0
- package/templates/claude/agents/pr-size-monitor/AGENT.md +330 -0
- package/templates/claude/commands/kiro/kiro-spec-impl.md +1 -1
- package/templates/claude/commands/michi/spec-impl.md +208 -35
- package/templates/claude-agent/commands/kiro/kiro-spec-impl.md +1 -1
- package/templates/cursor/commands/kiro/kiro-spec-impl.md +1 -1
- package/templates/multi-repo/docs/ci-status.md +51 -0
- package/templates/multi-repo/docs/release-notes.md +99 -0
- package/templates/multi-repo/overview/architecture.md +102 -0
- package/templates/multi-repo/overview/requirements.md +68 -0
- package/templates/multi-repo/overview/sequence.md +79 -0
- package/templates/multi-repo/steering/multi-repo.md +74 -0
- package/templates/multi-repo/tests/strategy.md +89 -0
- package/dist/scripts/__tests__/create-project.test.d.ts +0 -2
- package/dist/scripts/__tests__/create-project.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/create-project.test.js +0 -243
- package/dist/scripts/__tests__/create-project.test.js.map +0 -1
- package/dist/scripts/__tests__/jira-transitions.test.d.ts +0 -5
- package/dist/scripts/__tests__/jira-transitions.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/jira-transitions.test.js +0 -172
- package/dist/scripts/__tests__/jira-transitions.test.js.map +0 -1
- package/dist/scripts/__tests__/multi-project-estimate.test.d.ts +0 -2
- package/dist/scripts/__tests__/multi-project-estimate.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/multi-project-estimate.test.js +0 -118
- package/dist/scripts/__tests__/multi-project-estimate.test.js.map +0 -1
- package/dist/scripts/__tests__/setup-existing-project.test.d.ts +0 -2
- package/dist/scripts/__tests__/setup-existing-project.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/setup-existing-project.test.js +0 -208
- package/dist/scripts/__tests__/setup-existing-project.test.js.map +0 -1
- package/dist/scripts/__tests__/setup-interactive.test.d.ts +0 -2
- package/dist/scripts/__tests__/setup-interactive.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/setup-interactive.test.js +0 -166
- package/dist/scripts/__tests__/setup-interactive.test.js.map +0 -1
- package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts +0 -5
- package/dist/scripts/__tests__/spec-impl-workflow.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/spec-impl-workflow.test.js +0 -321
- package/dist/scripts/__tests__/spec-impl-workflow.test.js.map +0 -1
- package/dist/scripts/__tests__/spec-loader.test.d.ts +0 -5
- package/dist/scripts/__tests__/spec-loader.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/spec-loader.test.js +0 -153
- package/dist/scripts/__tests__/spec-loader.test.js.map +0 -1
- package/dist/scripts/__tests__/validate-phase.test.d.ts +0 -5
- package/dist/scripts/__tests__/validate-phase.test.d.ts.map +0 -1
- package/dist/scripts/__tests__/validate-phase.test.js +0 -249
- package/dist/scripts/__tests__/validate-phase.test.js.map +0 -1
- package/dist/scripts/constants/__tests__/environments.test.d.ts +0 -2
- package/dist/scripts/constants/__tests__/environments.test.d.ts.map +0 -1
- package/dist/scripts/constants/__tests__/environments.test.js +0 -125
- package/dist/scripts/constants/__tests__/environments.test.js.map +0 -1
- package/dist/scripts/constants/__tests__/languages.test.d.ts +0 -2
- package/dist/scripts/constants/__tests__/languages.test.d.ts.map +0 -1
- package/dist/scripts/constants/__tests__/languages.test.js +0 -82
- package/dist/scripts/constants/__tests__/languages.test.js.map +0 -1
- package/dist/scripts/create-project.d.ts +0 -16
- package/dist/scripts/create-project.d.ts.map +0 -1
- package/dist/scripts/create-project.js +0 -334
- package/dist/scripts/create-project.js.map +0 -1
- package/dist/scripts/list-projects.d.ts +0 -7
- package/dist/scripts/list-projects.d.ts.map +0 -1
- package/dist/scripts/list-projects.js +0 -88
- package/dist/scripts/list-projects.js.map +0 -1
- package/dist/scripts/template/__tests__/renderer.test.d.ts +0 -2
- package/dist/scripts/template/__tests__/renderer.test.d.ts.map +0 -1
- package/dist/scripts/template/__tests__/renderer.test.js +0 -165
- package/dist/scripts/template/__tests__/renderer.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/aidlc-parser.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/aidlc-parser.test.js +0 -315
- package/dist/scripts/utils/__tests__/aidlc-parser.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/business-days.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/business-days.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/business-days.test.js +0 -171
- package/dist/scripts/utils/__tests__/business-days.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/config-loader.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/config-loader.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/config-loader.test.js +0 -201
- package/dist/scripts/utils/__tests__/config-loader.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/config-validator.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/config-validator.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/config-validator.test.js +0 -394
- package/dist/scripts/utils/__tests__/config-validator.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/env-config.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/env-config.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/env-config.test.js +0 -218
- package/dist/scripts/utils/__tests__/env-config.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/feature-name-validator.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/feature-name-validator.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/feature-name-validator.test.js +0 -106
- package/dist/scripts/utils/__tests__/feature-name-validator.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js +0 -202
- package/dist/scripts/utils/__tests__/jira-issue-type-fetcher.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/spec-updater.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/spec-updater.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/spec-updater.test.js +0 -158
- package/dist/scripts/utils/__tests__/spec-updater.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/tasks-converter.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/tasks-converter.test.js +0 -500
- package/dist/scripts/utils/__tests__/tasks-converter.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.js +0 -314
- package/dist/scripts/utils/__tests__/tasks-format-validator.test.js.map +0 -1
- package/dist/scripts/utils/__tests__/test-runner.test.d.ts +0 -5
- package/dist/scripts/utils/__tests__/test-runner.test.d.ts.map +0 -1
- package/dist/scripts/utils/__tests__/test-runner.test.js +0 -64
- package/dist/scripts/utils/__tests__/test-runner.test.js.map +0 -1
- package/dist/src/__tests__/cli.test.d.ts +0 -5
- package/dist/src/__tests__/cli.test.d.ts.map +0 -1
- package/dist/src/__tests__/cli.test.js +0 -58
- package/dist/src/__tests__/cli.test.js.map +0 -1
- package/dist/src/__tests__/integration/internationalization.test.d.ts +0 -8
- package/dist/src/__tests__/integration/internationalization.test.d.ts.map +0 -1
- package/dist/src/__tests__/integration/internationalization.test.js +0 -333
- package/dist/src/__tests__/integration/internationalization.test.js.map +0 -1
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +0 -5
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/claude-agent.test.js +0 -122
- package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +0 -1
- package/dist/src/__tests__/integration/setup/claude.test.d.ts +0 -5
- package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/claude.test.js +0 -193
- package/dist/src/__tests__/integration/setup/claude.test.js.map +0 -1
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts +0 -5
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/cursor.test.js +0 -166
- package/dist/src/__tests__/integration/setup/cursor.test.js.map +0 -1
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +0 -32
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +0 -72
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +0 -1
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +0 -38
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/helpers/test-project.js +0 -83
- package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +0 -1
- package/dist/src/__tests__/integration/setup/init.test.d.ts +0 -5
- package/dist/src/__tests__/integration/setup/init.test.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/init.test.js +0 -352
- package/dist/src/__tests__/integration/setup/init.test.js.map +0 -1
- package/dist/src/__tests__/integration/setup/validation.test.d.ts +0 -5
- package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +0 -1
- package/dist/src/__tests__/integration/setup/validation.test.js +0 -301
- package/dist/src/__tests__/integration/setup/validation.test.js.map +0 -1
- package/scripts/create-project.ts +0 -386
- package/scripts/list-projects.ts +0 -112
|
@@ -147,6 +147,22 @@ describe('config-validator', () => {
|
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
describe('validateForConfluenceSync', () => {
|
|
150
|
+
let savedConfluenceSpace: string | undefined;
|
|
151
|
+
|
|
152
|
+
beforeEach(() => {
|
|
153
|
+
// 環境変数を保存
|
|
154
|
+
savedConfluenceSpace = process.env.CONFLUENCE_PRD_SPACE;
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
afterEach(() => {
|
|
158
|
+
// 環境変数を復元
|
|
159
|
+
if (savedConfluenceSpace !== undefined) {
|
|
160
|
+
process.env.CONFLUENCE_PRD_SPACE = savedConfluenceSpace;
|
|
161
|
+
} else {
|
|
162
|
+
delete process.env.CONFLUENCE_PRD_SPACE;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
150
166
|
it('spaces設定がない場合は警告を返す', () => {
|
|
151
167
|
// 環境変数をクリア
|
|
152
168
|
delete process.env.CONFLUENCE_PRD_SPACE;
|
|
@@ -236,6 +252,7 @@ describe('config-validator', () => {
|
|
|
236
252
|
});
|
|
237
253
|
|
|
238
254
|
it('環境変数CONFLUENCE_PRD_SPACEがある場合は情報メッセージ', () => {
|
|
255
|
+
// 環境変数を明示的に設定
|
|
239
256
|
process.env.CONFLUENCE_PRD_SPACE = 'Michi';
|
|
240
257
|
const configPath = join(testProjectRoot, '.michi/config.json');
|
|
241
258
|
writeFileSync(
|
|
@@ -259,23 +276,48 @@ describe('config-validator', () => {
|
|
|
259
276
|
});
|
|
260
277
|
|
|
261
278
|
describe('validateForJiraSync', () => {
|
|
279
|
+
let savedStoryEnv: string | undefined;
|
|
280
|
+
let savedSubtaskEnv: string | undefined;
|
|
281
|
+
|
|
262
282
|
beforeEach(() => {
|
|
263
|
-
//
|
|
283
|
+
// 環境変数を保存して削除
|
|
284
|
+
savedStoryEnv = process.env.JIRA_ISSUE_TYPE_STORY;
|
|
285
|
+
savedSubtaskEnv = process.env.JIRA_ISSUE_TYPE_SUBTASK;
|
|
264
286
|
delete process.env.JIRA_ISSUE_TYPE_STORY;
|
|
265
287
|
delete process.env.JIRA_ISSUE_TYPE_SUBTASK;
|
|
266
288
|
});
|
|
267
289
|
|
|
268
|
-
|
|
290
|
+
afterEach(() => {
|
|
291
|
+
// 環境変数を復元
|
|
292
|
+
if (savedStoryEnv !== undefined) {
|
|
293
|
+
process.env.JIRA_ISSUE_TYPE_STORY = savedStoryEnv;
|
|
294
|
+
} else {
|
|
295
|
+
delete process.env.JIRA_ISSUE_TYPE_STORY;
|
|
296
|
+
}
|
|
297
|
+
if (savedSubtaskEnv !== undefined) {
|
|
298
|
+
process.env.JIRA_ISSUE_TYPE_SUBTASK = savedSubtaskEnv;
|
|
299
|
+
} else {
|
|
300
|
+
delete process.env.JIRA_ISSUE_TYPE_SUBTASK;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('issueTypes.story設定がない場合はエラー(デフォルト設定なし)', () => {
|
|
269
305
|
const configPath = join(testProjectRoot, '.michi/config.json');
|
|
306
|
+
// issueTypes.storyを明示的にnullに設定してデフォルト値を無効化
|
|
270
307
|
writeFileSync(
|
|
271
308
|
configPath,
|
|
272
309
|
JSON.stringify({
|
|
273
|
-
jira: {
|
|
310
|
+
jira: {
|
|
311
|
+
issueTypes: {
|
|
312
|
+
story: null,
|
|
313
|
+
},
|
|
314
|
+
},
|
|
274
315
|
}),
|
|
275
316
|
);
|
|
276
317
|
|
|
277
318
|
const result = validateForJiraSync(testProjectRoot);
|
|
278
319
|
|
|
320
|
+
// story=nullの場合、環境変数もないのでエラーになる
|
|
279
321
|
expect(result.valid).toBe(false);
|
|
280
322
|
expect(result.errors.length).toBeGreaterThan(0);
|
|
281
323
|
expect(result.errors[0]).toContain('issueTypes.story');
|
|
@@ -301,6 +343,7 @@ describe('config-validator', () => {
|
|
|
301
343
|
});
|
|
302
344
|
|
|
303
345
|
it('環境変数JIRA_ISSUE_TYPE_STORYがある場合は情報メッセージ', () => {
|
|
346
|
+
// 環境変数を明示的に設定
|
|
304
347
|
process.env.JIRA_ISSUE_TYPE_STORY = '10036';
|
|
305
348
|
const configPath = join(testProjectRoot, '.michi/config.json');
|
|
306
349
|
writeFileSync(
|
|
@@ -322,7 +365,7 @@ describe('config-validator', () => {
|
|
|
322
365
|
}
|
|
323
366
|
});
|
|
324
367
|
|
|
325
|
-
it('issueTypes.subtask
|
|
368
|
+
it('issueTypes.subtask設定がない場合は警告(デフォルト設定なし)', () => {
|
|
326
369
|
const configPath = join(testProjectRoot, '.michi/config.json');
|
|
327
370
|
writeFileSync(
|
|
328
371
|
configPath,
|
|
@@ -330,6 +373,7 @@ describe('config-validator', () => {
|
|
|
330
373
|
jira: {
|
|
331
374
|
issueTypes: {
|
|
332
375
|
story: '10036',
|
|
376
|
+
subtask: null, // 明示的にnullに設定してデフォルト値を無効化
|
|
333
377
|
},
|
|
334
378
|
},
|
|
335
379
|
}),
|
|
@@ -337,6 +381,7 @@ describe('config-validator', () => {
|
|
|
337
381
|
|
|
338
382
|
const result = validateForJiraSync(testProjectRoot);
|
|
339
383
|
|
|
384
|
+
// subtask=nullの場合、環境変数もないので警告になる
|
|
340
385
|
expect(result.valid).toBe(true);
|
|
341
386
|
expect(result.warnings.length).toBeGreaterThan(0);
|
|
342
387
|
expect(result.warnings[0]).toContain('subtask');
|
|
@@ -365,8 +410,23 @@ describe('config-validator', () => {
|
|
|
365
410
|
});
|
|
366
411
|
|
|
367
412
|
describe('validateForJiraSyncAsync', () => {
|
|
413
|
+
let savedEnv: {
|
|
414
|
+
JIRA_ISSUE_TYPE_STORY?: string;
|
|
415
|
+
JIRA_ISSUE_TYPE_SUBTASK?: string;
|
|
416
|
+
ATLASSIAN_URL?: string;
|
|
417
|
+
ATLASSIAN_EMAIL?: string;
|
|
418
|
+
ATLASSIAN_API_TOKEN?: string;
|
|
419
|
+
};
|
|
420
|
+
|
|
368
421
|
beforeEach(() => {
|
|
369
|
-
//
|
|
422
|
+
// 環境変数を保存して削除
|
|
423
|
+
savedEnv = {
|
|
424
|
+
JIRA_ISSUE_TYPE_STORY: process.env.JIRA_ISSUE_TYPE_STORY,
|
|
425
|
+
JIRA_ISSUE_TYPE_SUBTASK: process.env.JIRA_ISSUE_TYPE_SUBTASK,
|
|
426
|
+
ATLASSIAN_URL: process.env.ATLASSIAN_URL,
|
|
427
|
+
ATLASSIAN_EMAIL: process.env.ATLASSIAN_EMAIL,
|
|
428
|
+
ATLASSIAN_API_TOKEN: process.env.ATLASSIAN_API_TOKEN,
|
|
429
|
+
};
|
|
370
430
|
delete process.env.JIRA_ISSUE_TYPE_STORY;
|
|
371
431
|
delete process.env.JIRA_ISSUE_TYPE_SUBTASK;
|
|
372
432
|
delete process.env.ATLASSIAN_URL;
|
|
@@ -374,6 +434,35 @@ describe('config-validator', () => {
|
|
|
374
434
|
delete process.env.ATLASSIAN_API_TOKEN;
|
|
375
435
|
});
|
|
376
436
|
|
|
437
|
+
afterEach(() => {
|
|
438
|
+
// 環境変数を復元
|
|
439
|
+
if (savedEnv.JIRA_ISSUE_TYPE_STORY !== undefined) {
|
|
440
|
+
process.env.JIRA_ISSUE_TYPE_STORY = savedEnv.JIRA_ISSUE_TYPE_STORY;
|
|
441
|
+
} else {
|
|
442
|
+
delete process.env.JIRA_ISSUE_TYPE_STORY;
|
|
443
|
+
}
|
|
444
|
+
if (savedEnv.JIRA_ISSUE_TYPE_SUBTASK !== undefined) {
|
|
445
|
+
process.env.JIRA_ISSUE_TYPE_SUBTASK = savedEnv.JIRA_ISSUE_TYPE_SUBTASK;
|
|
446
|
+
} else {
|
|
447
|
+
delete process.env.JIRA_ISSUE_TYPE_SUBTASK;
|
|
448
|
+
}
|
|
449
|
+
if (savedEnv.ATLASSIAN_URL !== undefined) {
|
|
450
|
+
process.env.ATLASSIAN_URL = savedEnv.ATLASSIAN_URL;
|
|
451
|
+
} else {
|
|
452
|
+
delete process.env.ATLASSIAN_URL;
|
|
453
|
+
}
|
|
454
|
+
if (savedEnv.ATLASSIAN_EMAIL !== undefined) {
|
|
455
|
+
process.env.ATLASSIAN_EMAIL = savedEnv.ATLASSIAN_EMAIL;
|
|
456
|
+
} else {
|
|
457
|
+
delete process.env.ATLASSIAN_EMAIL;
|
|
458
|
+
}
|
|
459
|
+
if (savedEnv.ATLASSIAN_API_TOKEN !== undefined) {
|
|
460
|
+
process.env.ATLASSIAN_API_TOKEN = savedEnv.ATLASSIAN_API_TOKEN;
|
|
461
|
+
} else {
|
|
462
|
+
delete process.env.ATLASSIAN_API_TOKEN;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
377
466
|
it('認証情報が未設定の場合は同期版と同じ結果を返す', async () => {
|
|
378
467
|
const configPath = join(testProjectRoot, '.michi/config.json');
|
|
379
468
|
writeFileSync(
|
|
@@ -393,6 +482,8 @@ describe('config-validator', () => {
|
|
|
393
482
|
writeFileSync(
|
|
394
483
|
projectJsonPath,
|
|
395
484
|
JSON.stringify({
|
|
485
|
+
projectId: 'test-project',
|
|
486
|
+
projectName: 'Test Project',
|
|
396
487
|
jiraProjectKey: 'TEST',
|
|
397
488
|
}),
|
|
398
489
|
);
|
|
@@ -404,6 +495,7 @@ describe('config-validator', () => {
|
|
|
404
495
|
});
|
|
405
496
|
|
|
406
497
|
it('認証情報が設定されていて、Issue Type IDが存在する場合は成功', async () => {
|
|
498
|
+
// 環境変数を明示的に設定
|
|
407
499
|
process.env.ATLASSIAN_URL = 'https://test.atlassian.net';
|
|
408
500
|
process.env.ATLASSIAN_EMAIL = 'test@example.com';
|
|
409
501
|
process.env.ATLASSIAN_API_TOKEN = 'test-token';
|
|
@@ -449,16 +541,23 @@ describe('config-validator', () => {
|
|
|
449
541
|
});
|
|
450
542
|
|
|
451
543
|
it('認証情報が設定されていて、Issue Type IDが存在しない場合はエラー', async () => {
|
|
544
|
+
// 環境変数を明示的に設定(既存の環境変数を上書き)
|
|
452
545
|
process.env.ATLASSIAN_URL = 'https://test.atlassian.net';
|
|
453
546
|
process.env.ATLASSIAN_EMAIL = 'test@example.com';
|
|
454
547
|
process.env.ATLASSIAN_API_TOKEN = 'test-token';
|
|
455
548
|
process.env.JIRA_ISSUE_TYPE_STORY = '99999'; // 存在しないID
|
|
456
549
|
|
|
457
550
|
const configPath = join(testProjectRoot, '.michi/config.json');
|
|
551
|
+
// issueTypes.storyを環境変数から取得するように空にする
|
|
552
|
+
// (デフォルト値を使わないように明示的にnullに設定)
|
|
458
553
|
writeFileSync(
|
|
459
554
|
configPath,
|
|
460
555
|
JSON.stringify({
|
|
461
|
-
jira: {
|
|
556
|
+
jira: {
|
|
557
|
+
issueTypes: {
|
|
558
|
+
story: null, // 環境変数から取得
|
|
559
|
+
},
|
|
560
|
+
},
|
|
462
561
|
}),
|
|
463
562
|
);
|
|
464
563
|
|
|
@@ -499,6 +598,7 @@ describe('config-validator', () => {
|
|
|
499
598
|
});
|
|
500
599
|
|
|
501
600
|
it('JIRA API取得に失敗した場合は警告を追加するがエラーにはしない', async () => {
|
|
601
|
+
// 環境変数を明示的に設定
|
|
502
602
|
process.env.ATLASSIAN_URL = 'https://test.atlassian.net';
|
|
503
603
|
process.env.ATLASSIAN_EMAIL = 'test@example.com';
|
|
504
604
|
process.env.ATLASSIAN_API_TOKEN = 'test-token';
|
|
@@ -185,7 +185,6 @@ URL_WITH_PARAMS=https://example.com?param1=value1¶m2=value2
|
|
|
185
185
|
['ATLASSIAN_API_TOKEN', 'token123'],
|
|
186
186
|
['GITHUB_ORG', 'myorg'],
|
|
187
187
|
['GITHUB_TOKEN', 'ghp_xxx'],
|
|
188
|
-
['GITHUB_REPO', 'myorg/myrepo'],
|
|
189
188
|
['CONFLUENCE_PRD_SPACE', 'PRD'],
|
|
190
189
|
['CONFLUENCE_QA_SPACE', 'QA'],
|
|
191
190
|
['CONFLUENCE_RELEASE_SPACE', 'RELEASE'],
|
|
@@ -217,7 +216,6 @@ ATLASSIAN_API_TOKEN=test_token_123
|
|
|
217
216
|
# GitHub設定
|
|
218
217
|
GITHUB_ORG=testorg
|
|
219
218
|
GITHUB_TOKEN=ghp_test123
|
|
220
|
-
GITHUB_REPO=testorg/testrepo
|
|
221
219
|
|
|
222
220
|
# Confluence共有スペース
|
|
223
221
|
CONFLUENCE_PRD_SPACE=PRD
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Repo バリデーション関数のテスト
|
|
3
|
+
* Task 1.2: バリデーション関数の実装
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import {
|
|
8
|
+
validateProjectName,
|
|
9
|
+
validateJiraKey,
|
|
10
|
+
validateRepositoryUrl,
|
|
11
|
+
} from '../multi-repo-validator';
|
|
12
|
+
|
|
13
|
+
describe('validateProjectName', () => {
|
|
14
|
+
describe('正常ケース', () => {
|
|
15
|
+
it('有効なプロジェクト名を受け入れる', () => {
|
|
16
|
+
const validNames = [
|
|
17
|
+
'my-project',
|
|
18
|
+
'プロジェクト名',
|
|
19
|
+
'project_v2',
|
|
20
|
+
'My Project 123',
|
|
21
|
+
'a',
|
|
22
|
+
'a'.repeat(100),
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
validNames.forEach((name) => {
|
|
26
|
+
const result = validateProjectName(name);
|
|
27
|
+
expect(result.isValid).toBe(true);
|
|
28
|
+
expect(result.errors).toHaveLength(0);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('パストラバーサル対策', () => {
|
|
34
|
+
it('スラッシュ(/)を含む場合はエラー', () => {
|
|
35
|
+
const result = validateProjectName('project/name');
|
|
36
|
+
expect(result.isValid).toBe(false);
|
|
37
|
+
expect(result.errors).toContain(
|
|
38
|
+
'Project name must not contain path traversal characters (/, \\)',
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('バックスラッシュ(\\)を含む場合はエラー', () => {
|
|
43
|
+
const result = validateProjectName('project\\name');
|
|
44
|
+
expect(result.isValid).toBe(false);
|
|
45
|
+
expect(result.errors).toContain(
|
|
46
|
+
'Project name must not contain path traversal characters (/, \\)',
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('../を含む場合はエラー', () => {
|
|
51
|
+
const result = validateProjectName('../etc/passwd');
|
|
52
|
+
expect(result.isValid).toBe(false);
|
|
53
|
+
expect(result.errors).toContain(
|
|
54
|
+
'Project name must not contain path traversal characters (/, \\)',
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('/を含む場合はエラー', () => {
|
|
59
|
+
const result = validateProjectName('/etc/passwd');
|
|
60
|
+
expect(result.isValid).toBe(false);
|
|
61
|
+
expect(result.errors).toContain(
|
|
62
|
+
'Project name must not contain path traversal characters (/, \\)',
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('相対パス対策', () => {
|
|
68
|
+
it('ドット(.)単独の場合はエラー', () => {
|
|
69
|
+
const result = validateProjectName('.');
|
|
70
|
+
expect(result.isValid).toBe(false);
|
|
71
|
+
expect(result.errors).toContain(
|
|
72
|
+
'Project name must not be relative path components (., ..)',
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('ダブルドット(..)単独の場合はエラー', () => {
|
|
77
|
+
const result = validateProjectName('..');
|
|
78
|
+
expect(result.isValid).toBe(false);
|
|
79
|
+
expect(result.errors).toContain(
|
|
80
|
+
'Project name must not be relative path components (., ..)',
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('制御文字対策', () => {
|
|
86
|
+
it('ヌル文字(\\x00)を含む場合はエラー', () => {
|
|
87
|
+
const result = validateProjectName('project\x00name');
|
|
88
|
+
expect(result.isValid).toBe(false);
|
|
89
|
+
expect(result.errors).toContain(
|
|
90
|
+
'Project name must not contain control characters',
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('タブ文字(\\t)を含む場合はエラー', () => {
|
|
95
|
+
const result = validateProjectName('project\tname');
|
|
96
|
+
expect(result.isValid).toBe(false);
|
|
97
|
+
expect(result.errors).toContain(
|
|
98
|
+
'Project name must not contain control characters',
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('改行文字(\\n)を含む場合はエラー', () => {
|
|
103
|
+
const result = validateProjectName('project\nname');
|
|
104
|
+
expect(result.isValid).toBe(false);
|
|
105
|
+
expect(result.errors).toContain(
|
|
106
|
+
'Project name must not contain control characters',
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('改行文字(\\r)を含む場合はエラー', () => {
|
|
111
|
+
const result = validateProjectName('project\rname');
|
|
112
|
+
expect(result.isValid).toBe(false);
|
|
113
|
+
expect(result.errors).toContain(
|
|
114
|
+
'Project name must not contain control characters',
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('エスケープ文字(\\x1B)を含む場合はエラー', () => {
|
|
119
|
+
const result = validateProjectName('project\x1Bname');
|
|
120
|
+
expect(result.isValid).toBe(false);
|
|
121
|
+
expect(result.errors).toContain(
|
|
122
|
+
'Project name must not contain control characters',
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('削除文字(\\x7F)を含む場合はエラー', () => {
|
|
127
|
+
const result = validateProjectName('project\x7Fname');
|
|
128
|
+
expect(result.isValid).toBe(false);
|
|
129
|
+
expect(result.errors).toContain(
|
|
130
|
+
'Project name must not contain control characters',
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('長さチェック', () => {
|
|
136
|
+
it('101文字以上の場合はエラー', () => {
|
|
137
|
+
const longName = 'a'.repeat(101);
|
|
138
|
+
const result = validateProjectName(longName);
|
|
139
|
+
expect(result.isValid).toBe(false);
|
|
140
|
+
expect(result.errors).toContain(
|
|
141
|
+
'Project name must be between 1 and 100 characters',
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('空文字列の場合はエラー', () => {
|
|
146
|
+
const result = validateProjectName('');
|
|
147
|
+
expect(result.isValid).toBe(false);
|
|
148
|
+
expect(result.errors).toContain(
|
|
149
|
+
'Project name must be between 1 and 100 characters',
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('100文字の場合は正常', () => {
|
|
154
|
+
const name = 'a'.repeat(100);
|
|
155
|
+
const result = validateProjectName(name);
|
|
156
|
+
expect(result.isValid).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('1文字の場合は正常', () => {
|
|
160
|
+
const result = validateProjectName('a');
|
|
161
|
+
expect(result.isValid).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe('validateJiraKey', () => {
|
|
167
|
+
describe('正常ケース', () => {
|
|
168
|
+
it('2-10文字の大文字英字を受け入れる', () => {
|
|
169
|
+
const validKeys = ['AB', 'PROJ', 'TICKET', 'ABCDEFGHIJ'];
|
|
170
|
+
|
|
171
|
+
validKeys.forEach((key) => {
|
|
172
|
+
const result = validateJiraKey(key);
|
|
173
|
+
expect(result.isValid).toBe(true);
|
|
174
|
+
expect(result.errors).toHaveLength(0);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('異常ケース', () => {
|
|
180
|
+
it('小文字を含む場合はエラー', () => {
|
|
181
|
+
const result = validateJiraKey('abc');
|
|
182
|
+
expect(result.isValid).toBe(false);
|
|
183
|
+
expect(result.errors).toContain(
|
|
184
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('1文字の場合はエラー', () => {
|
|
189
|
+
const result = validateJiraKey('A');
|
|
190
|
+
expect(result.isValid).toBe(false);
|
|
191
|
+
expect(result.errors).toContain(
|
|
192
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('11文字以上の場合はエラー', () => {
|
|
197
|
+
const result = validateJiraKey('ABCDEFGHIJK');
|
|
198
|
+
expect(result.isValid).toBe(false);
|
|
199
|
+
expect(result.errors).toContain(
|
|
200
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('数字を含む場合はエラー', () => {
|
|
205
|
+
const result = validateJiraKey('ABC123');
|
|
206
|
+
expect(result.isValid).toBe(false);
|
|
207
|
+
expect(result.errors).toContain(
|
|
208
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('空文字列の場合はエラー', () => {
|
|
213
|
+
const result = validateJiraKey('');
|
|
214
|
+
expect(result.isValid).toBe(false);
|
|
215
|
+
expect(result.errors).toContain(
|
|
216
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('ハイフンを含む場合はエラー', () => {
|
|
221
|
+
const result = validateJiraKey('ABC-DEF');
|
|
222
|
+
expect(result.isValid).toBe(false);
|
|
223
|
+
expect(result.errors).toContain(
|
|
224
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('スペースを含む場合はエラー', () => {
|
|
229
|
+
const result = validateJiraKey('ABC DEF');
|
|
230
|
+
expect(result.isValid).toBe(false);
|
|
231
|
+
expect(result.errors).toContain(
|
|
232
|
+
'JIRA key must be 2-10 uppercase letters',
|
|
233
|
+
);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('validateRepositoryUrl', () => {
|
|
239
|
+
describe('正常ケース', () => {
|
|
240
|
+
it('有効なGitHub HTTPS URLを受け入れる', () => {
|
|
241
|
+
const validUrls = [
|
|
242
|
+
'https://github.com/owner/repo',
|
|
243
|
+
'https://github.com/my-org/my-repo',
|
|
244
|
+
'https://github.com/user123/project-name',
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
validUrls.forEach((url) => {
|
|
248
|
+
const result = validateRepositoryUrl(url);
|
|
249
|
+
expect(result.isValid).toBe(true);
|
|
250
|
+
expect(result.errors).toHaveLength(0);
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
describe('異常ケース', () => {
|
|
256
|
+
it('GitLab URLの場合はエラー', () => {
|
|
257
|
+
const result = validateRepositoryUrl(
|
|
258
|
+
'https://gitlab.com/owner/repo',
|
|
259
|
+
);
|
|
260
|
+
expect(result.isValid).toBe(false);
|
|
261
|
+
expect(result.errors).toContain(
|
|
262
|
+
'Repository URL must be in GitHub format: https://github.com/{owner}/{repo}',
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('HTTP URLの場合はエラー', () => {
|
|
267
|
+
const result = validateRepositoryUrl('http://github.com/owner/repo');
|
|
268
|
+
expect(result.isValid).toBe(false);
|
|
269
|
+
expect(result.errors).toContain(
|
|
270
|
+
'Repository URL must use HTTPS protocol',
|
|
271
|
+
);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('SSH URLの場合はエラー', () => {
|
|
275
|
+
const result = validateRepositoryUrl('git@github.com:owner/repo.git');
|
|
276
|
+
expect(result.isValid).toBe(false);
|
|
277
|
+
expect(result.errors).toContain(
|
|
278
|
+
'Repository URL must be in GitHub format: https://github.com/{owner}/{repo}',
|
|
279
|
+
);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('不完全なURLの場合はエラー', () => {
|
|
283
|
+
const result = validateRepositoryUrl('https://github.com/owner');
|
|
284
|
+
expect(result.isValid).toBe(false);
|
|
285
|
+
expect(result.errors).toContain(
|
|
286
|
+
'Repository URL must be in GitHub format: https://github.com/{owner}/{repo}',
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('空文字列の場合はエラー', () => {
|
|
291
|
+
const result = validateRepositoryUrl('');
|
|
292
|
+
expect(result.isValid).toBe(false);
|
|
293
|
+
expect(result.errors).toContain('Repository URL is empty');
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('無効なURL形式の場合はエラー', () => {
|
|
297
|
+
const result = validateRepositoryUrl('not-a-url');
|
|
298
|
+
expect(result.isValid).toBe(false);
|
|
299
|
+
expect(result.errors).toContain('Repository URL format is invalid');
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('.git拡張子を含む場合はエラー', () => {
|
|
303
|
+
const result = validateRepositoryUrl(
|
|
304
|
+
'https://github.com/owner/repo.git',
|
|
305
|
+
);
|
|
306
|
+
expect(result.isValid).toBe(false);
|
|
307
|
+
expect(result.errors).toContain(
|
|
308
|
+
'Repository URL must not include .git extension',
|
|
309
|
+
);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
describe('プレースホルダー検出', () => {
|
|
314
|
+
it('プレースホルダーURLの場合はエラー', () => {
|
|
315
|
+
const placeholders = [
|
|
316
|
+
'https://github.com/your-org/your-repo',
|
|
317
|
+
'https://github.com/owner/repo-name',
|
|
318
|
+
];
|
|
319
|
+
|
|
320
|
+
placeholders.forEach((url) => {
|
|
321
|
+
const result = validateRepositoryUrl(url);
|
|
322
|
+
if (
|
|
323
|
+
url.includes('your-org') ||
|
|
324
|
+
url.includes('your-repo') ||
|
|
325
|
+
url.includes('repo-name')
|
|
326
|
+
) {
|
|
327
|
+
expect(result.isValid).toBe(false);
|
|
328
|
+
expect(result.errors).toContain(
|
|
329
|
+
'Repository URL contains placeholder values',
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
});
|