@shirokuma-library/shirokuma-docs 0.1.0-alpha.10
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.
Potentially problematic release.
This version of @shirokuma-library/shirokuma-docs might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.en.md +346 -0
- package/README.md +346 -0
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/bin/shirokuma-docs +2 -0
- package/dist/analyzers/details-test-analysis.d.ts +31 -0
- package/dist/analyzers/details-test-analysis.d.ts.map +1 -0
- package/dist/analyzers/details-test-analysis.js +174 -0
- package/dist/analyzers/details-test-analysis.js.map +1 -0
- package/dist/analyzers/feature-map-builder.d.ts +20 -0
- package/dist/analyzers/feature-map-builder.d.ts.map +1 -0
- package/dist/analyzers/feature-map-builder.js +154 -0
- package/dist/analyzers/feature-map-builder.js.map +1 -0
- package/dist/analyzers/feature-map-references.d.ts +34 -0
- package/dist/analyzers/feature-map-references.d.ts.map +1 -0
- package/dist/analyzers/feature-map-references.js +249 -0
- package/dist/analyzers/feature-map-references.js.map +1 -0
- package/dist/analyzers/reference-analyzer.d.ts +95 -0
- package/dist/analyzers/reference-analyzer.d.ts.map +1 -0
- package/dist/analyzers/reference-analyzer.js +372 -0
- package/dist/analyzers/reference-analyzer.js.map +1 -0
- package/dist/commands/adr.d.ts +26 -0
- package/dist/commands/adr.d.ts.map +1 -0
- package/dist/commands/adr.js +129 -0
- package/dist/commands/adr.js.map +1 -0
- package/dist/commands/api-tools.d.ts +83 -0
- package/dist/commands/api-tools.d.ts.map +1 -0
- package/dist/commands/api-tools.js +775 -0
- package/dist/commands/api-tools.js.map +1 -0
- package/dist/commands/coverage.d.ts +139 -0
- package/dist/commands/coverage.d.ts.map +1 -0
- package/dist/commands/coverage.js +481 -0
- package/dist/commands/coverage.js.map +1 -0
- package/dist/commands/deps.d.ts +24 -0
- package/dist/commands/deps.d.ts.map +1 -0
- package/dist/commands/deps.js +211 -0
- package/dist/commands/deps.js.map +1 -0
- package/dist/commands/details-context.d.ts +38 -0
- package/dist/commands/details-context.d.ts.map +1 -0
- package/dist/commands/details-context.js +195 -0
- package/dist/commands/details-context.js.map +1 -0
- package/dist/commands/details-types.d.ts +315 -0
- package/dist/commands/details-types.d.ts.map +1 -0
- package/dist/commands/details-types.js +7 -0
- package/dist/commands/details-types.js.map +1 -0
- package/dist/commands/details.d.ts +24 -0
- package/dist/commands/details.d.ts.map +1 -0
- package/dist/commands/details.js +299 -0
- package/dist/commands/details.js.map +1 -0
- package/dist/commands/discussion-templates.d.ts +26 -0
- package/dist/commands/discussion-templates.d.ts.map +1 -0
- package/dist/commands/discussion-templates.js +270 -0
- package/dist/commands/discussion-templates.js.map +1 -0
- package/dist/commands/discussions.d.ts +31 -0
- package/dist/commands/discussions.d.ts.map +1 -0
- package/dist/commands/discussions.js +744 -0
- package/dist/commands/discussions.js.map +1 -0
- package/dist/commands/feature-map-types.d.ts +294 -0
- package/dist/commands/feature-map-types.d.ts.map +1 -0
- package/dist/commands/feature-map-types.js +8 -0
- package/dist/commands/feature-map-types.js.map +1 -0
- package/dist/commands/feature-map.d.ts +30 -0
- package/dist/commands/feature-map.d.ts.map +1 -0
- package/dist/commands/feature-map.js +137 -0
- package/dist/commands/feature-map.js.map +1 -0
- package/dist/commands/generate.d.ts +16 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +88 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/gh-discussions.d.ts +31 -0
- package/dist/commands/gh-discussions.d.ts.map +1 -0
- package/dist/commands/gh-discussions.js +743 -0
- package/dist/commands/gh-discussions.js.map +1 -0
- package/dist/commands/gh-issues-pr.d.ts +74 -0
- package/dist/commands/gh-issues-pr.d.ts.map +1 -0
- package/dist/commands/gh-issues-pr.js +417 -0
- package/dist/commands/gh-issues-pr.js.map +1 -0
- package/dist/commands/gh-issues.d.ts +90 -0
- package/dist/commands/gh-issues.d.ts.map +1 -0
- package/dist/commands/gh-issues.js +1297 -0
- package/dist/commands/gh-issues.js.map +1 -0
- package/dist/commands/gh-projects.d.ts +54 -0
- package/dist/commands/gh-projects.d.ts.map +1 -0
- package/dist/commands/gh-projects.js +966 -0
- package/dist/commands/gh-projects.js.map +1 -0
- package/dist/commands/gh-repo.d.ts +18 -0
- package/dist/commands/gh-repo.d.ts.map +1 -0
- package/dist/commands/gh-repo.js +253 -0
- package/dist/commands/gh-repo.js.map +1 -0
- package/dist/commands/github-data.d.ts +67 -0
- package/dist/commands/github-data.d.ts.map +1 -0
- package/dist/commands/github-data.js +361 -0
- package/dist/commands/github-data.js.map +1 -0
- package/dist/commands/i18n.d.ts +102 -0
- package/dist/commands/i18n.d.ts.map +1 -0
- package/dist/commands/i18n.js +829 -0
- package/dist/commands/i18n.js.map +1 -0
- package/dist/commands/impact.d.ts +14 -0
- package/dist/commands/impact.d.ts.map +1 -0
- package/dist/commands/impact.js +263 -0
- package/dist/commands/impact.js.map +1 -0
- package/dist/commands/init.d.ts +53 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +468 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/issues-pr.d.ts +83 -0
- package/dist/commands/issues-pr.d.ts.map +1 -0
- package/dist/commands/issues-pr.js +572 -0
- package/dist/commands/issues-pr.js.map +1 -0
- package/dist/commands/issues.d.ts +78 -0
- package/dist/commands/issues.d.ts.map +1 -0
- package/dist/commands/issues.js +1541 -0
- package/dist/commands/issues.js.map +1 -0
- package/dist/commands/link-docs.d.ts +21 -0
- package/dist/commands/link-docs.d.ts.map +1 -0
- package/dist/commands/link-docs.js +990 -0
- package/dist/commands/link-docs.js.map +1 -0
- package/dist/commands/lint-annotations.d.ts +28 -0
- package/dist/commands/lint-annotations.d.ts.map +1 -0
- package/dist/commands/lint-annotations.js +511 -0
- package/dist/commands/lint-annotations.js.map +1 -0
- package/dist/commands/lint-code.d.ts +26 -0
- package/dist/commands/lint-code.d.ts.map +1 -0
- package/dist/commands/lint-code.js +428 -0
- package/dist/commands/lint-code.js.map +1 -0
- package/dist/commands/lint-coverage.d.ts +33 -0
- package/dist/commands/lint-coverage.d.ts.map +1 -0
- package/dist/commands/lint-coverage.js +379 -0
- package/dist/commands/lint-coverage.js.map +1 -0
- package/dist/commands/lint-docs.d.ts +23 -0
- package/dist/commands/lint-docs.d.ts.map +1 -0
- package/dist/commands/lint-docs.js +338 -0
- package/dist/commands/lint-docs.js.map +1 -0
- package/dist/commands/lint-structure.d.ts +38 -0
- package/dist/commands/lint-structure.d.ts.map +1 -0
- package/dist/commands/lint-structure.js +350 -0
- package/dist/commands/lint-structure.js.map +1 -0
- package/dist/commands/lint-tests.d.ts +25 -0
- package/dist/commands/lint-tests.d.ts.map +1 -0
- package/dist/commands/lint-tests.js +105 -0
- package/dist/commands/lint-tests.js.map +1 -0
- package/dist/commands/lint-workflow.d.ts +36 -0
- package/dist/commands/lint-workflow.d.ts.map +1 -0
- package/dist/commands/lint-workflow.js +255 -0
- package/dist/commands/lint-workflow.js.map +1 -0
- package/dist/commands/overview.d.ts +21 -0
- package/dist/commands/overview.d.ts.map +1 -0
- package/dist/commands/overview.js +1300 -0
- package/dist/commands/overview.js.map +1 -0
- package/dist/commands/packages.d.ts +107 -0
- package/dist/commands/packages.d.ts.map +1 -0
- package/dist/commands/packages.js +308 -0
- package/dist/commands/packages.js.map +1 -0
- package/dist/commands/portal-nextjs.d.ts +23 -0
- package/dist/commands/portal-nextjs.d.ts.map +1 -0
- package/dist/commands/portal-nextjs.js +336 -0
- package/dist/commands/portal-nextjs.js.map +1 -0
- package/dist/commands/portal.d.ts +24 -0
- package/dist/commands/portal.d.ts.map +1 -0
- package/dist/commands/portal.js +16 -0
- package/dist/commands/portal.js.map +1 -0
- package/dist/commands/projects.d.ts +54 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +1191 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/repo-pairs.d.ts +19 -0
- package/dist/commands/repo-pairs.d.ts.map +1 -0
- package/dist/commands/repo-pairs.js +529 -0
- package/dist/commands/repo-pairs.js.map +1 -0
- package/dist/commands/repo.d.ts +18 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +253 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/commands/schema.d.ts +49 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +830 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/screenshots.d.ts +203 -0
- package/dist/commands/screenshots.d.ts.map +1 -0
- package/dist/commands/screenshots.js +1234 -0
- package/dist/commands/screenshots.js.map +1 -0
- package/dist/commands/search-index.d.ts +83 -0
- package/dist/commands/search-index.d.ts.map +1 -0
- package/dist/commands/search-index.js +389 -0
- package/dist/commands/search-index.js.map +1 -0
- package/dist/commands/search.d.ts +24 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +254 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/session.d.ts +159 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +1274 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/test-cases-types.d.ts +154 -0
- package/dist/commands/test-cases-types.d.ts.map +1 -0
- package/dist/commands/test-cases-types.js +7 -0
- package/dist/commands/test-cases-types.js.map +1 -0
- package/dist/commands/test-cases.d.ts +28 -0
- package/dist/commands/test-cases.d.ts.map +1 -0
- package/dist/commands/test-cases.js +192 -0
- package/dist/commands/test-cases.js.map +1 -0
- package/dist/commands/typedoc.d.ts +21 -0
- package/dist/commands/typedoc.d.ts.map +1 -0
- package/dist/commands/typedoc.js +192 -0
- package/dist/commands/typedoc.js.map +1 -0
- package/dist/commands/update-skills.d.ts +56 -0
- package/dist/commands/update-skills.d.ts.map +1 -0
- package/dist/commands/update-skills.js +626 -0
- package/dist/commands/update-skills.js.map +1 -0
- package/dist/generators/details-entity-pages.d.ts +40 -0
- package/dist/generators/details-entity-pages.d.ts.map +1 -0
- package/dist/generators/details-entity-pages.js +301 -0
- package/dist/generators/details-entity-pages.js.map +1 -0
- package/dist/generators/details-html.d.ts +23 -0
- package/dist/generators/details-html.d.ts.map +1 -0
- package/dist/generators/details-html.js +324 -0
- package/dist/generators/details-html.js.map +1 -0
- package/dist/generators/details-module-page.d.ts +33 -0
- package/dist/generators/details-module-page.d.ts.map +1 -0
- package/dist/generators/details-module-page.js +408 -0
- package/dist/generators/details-module-page.js.map +1 -0
- package/dist/generators/details-styles.d.ts +39 -0
- package/dist/generators/details-styles.d.ts.map +1 -0
- package/dist/generators/details-styles.js +409 -0
- package/dist/generators/details-styles.js.map +1 -0
- package/dist/generators/feature-map-html.d.ts +66 -0
- package/dist/generators/feature-map-html.d.ts.map +1 -0
- package/dist/generators/feature-map-html.js +569 -0
- package/dist/generators/feature-map-html.js.map +1 -0
- package/dist/generators/feature-map-styles.d.ts +39 -0
- package/dist/generators/feature-map-styles.d.ts.map +1 -0
- package/dist/generators/feature-map-styles.js +449 -0
- package/dist/generators/feature-map-styles.js.map +1 -0
- package/dist/generators/test-cases-hierarchy.d.ts +21 -0
- package/dist/generators/test-cases-hierarchy.d.ts.map +1 -0
- package/dist/generators/test-cases-hierarchy.js +336 -0
- package/dist/generators/test-cases-hierarchy.js.map +1 -0
- package/dist/generators/test-cases-main.d.ts +20 -0
- package/dist/generators/test-cases-main.d.ts.map +1 -0
- package/dist/generators/test-cases-main.js +439 -0
- package/dist/generators/test-cases-main.js.map +1 -0
- package/dist/generators/test-cases-styles.d.ts +64 -0
- package/dist/generators/test-cases-styles.d.ts.map +1 -0
- package/dist/generators/test-cases-styles.js +1277 -0
- package/dist/generators/test-cases-styles.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +600 -0
- package/dist/index.js.map +1 -0
- package/dist/lint/annotation-lint.d.ts +198 -0
- package/dist/lint/annotation-lint.d.ts.map +1 -0
- package/dist/lint/annotation-lint.js +510 -0
- package/dist/lint/annotation-lint.js.map +1 -0
- package/dist/lint/annotation-types.d.ts +161 -0
- package/dist/lint/annotation-types.d.ts.map +1 -0
- package/dist/lint/annotation-types.js +31 -0
- package/dist/lint/annotation-types.js.map +1 -0
- package/dist/lint/code-types.d.ts +135 -0
- package/dist/lint/code-types.d.ts.map +1 -0
- package/dist/lint/code-types.js +25 -0
- package/dist/lint/code-types.js.map +1 -0
- package/dist/lint/coverage-types.d.ts +128 -0
- package/dist/lint/coverage-types.d.ts.map +1 -0
- package/dist/lint/coverage-types.js +24 -0
- package/dist/lint/coverage-types.js.map +1 -0
- package/dist/lint/docs-types.d.ts +214 -0
- package/dist/lint/docs-types.d.ts.map +1 -0
- package/dist/lint/docs-types.js +18 -0
- package/dist/lint/docs-types.js.map +1 -0
- package/dist/lint/formatters/index.d.ts +14 -0
- package/dist/lint/formatters/index.d.ts.map +1 -0
- package/dist/lint/formatters/index.js +28 -0
- package/dist/lint/formatters/index.js.map +1 -0
- package/dist/lint/formatters/json.d.ts +11 -0
- package/dist/lint/formatters/json.d.ts.map +1 -0
- package/dist/lint/formatters/json.js +12 -0
- package/dist/lint/formatters/json.js.map +1 -0
- package/dist/lint/formatters/summary.d.ts +11 -0
- package/dist/lint/formatters/summary.d.ts.map +1 -0
- package/dist/lint/formatters/summary.js +37 -0
- package/dist/lint/formatters/summary.js.map +1 -0
- package/dist/lint/formatters/terminal.d.ts +11 -0
- package/dist/lint/formatters/terminal.d.ts.map +1 -0
- package/dist/lint/formatters/terminal.js +99 -0
- package/dist/lint/formatters/terminal.js.map +1 -0
- package/dist/lint/index.d.ts +18 -0
- package/dist/lint/index.d.ts.map +1 -0
- package/dist/lint/index.js +103 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/rules/annotation-required.d.ts +35 -0
- package/dist/lint/rules/annotation-required.d.ts.map +1 -0
- package/dist/lint/rules/annotation-required.js +127 -0
- package/dist/lint/rules/annotation-required.js.map +1 -0
- package/dist/lint/rules/code-rules.d.ts +12 -0
- package/dist/lint/rules/code-rules.d.ts.map +1 -0
- package/dist/lint/rules/code-rules.js +11 -0
- package/dist/lint/rules/code-rules.js.map +1 -0
- package/dist/lint/rules/describe-coverage.d.ts +8 -0
- package/dist/lint/rules/describe-coverage.d.ts.map +1 -0
- package/dist/lint/rules/describe-coverage.js +43 -0
- package/dist/lint/rules/describe-coverage.js.map +1 -0
- package/dist/lint/rules/duplicate-testdoc.d.ts +8 -0
- package/dist/lint/rules/duplicate-testdoc.d.ts.map +1 -0
- package/dist/lint/rules/duplicate-testdoc.js +38 -0
- package/dist/lint/rules/duplicate-testdoc.js.map +1 -0
- package/dist/lint/rules/index.d.ts +29 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/index.js +55 -0
- package/dist/lint/rules/index.js.map +1 -0
- package/dist/lint/rules/server-action-structure.d.ts +37 -0
- package/dist/lint/rules/server-action-structure.d.ts.map +1 -0
- package/dist/lint/rules/server-action-structure.js +152 -0
- package/dist/lint/rules/server-action-structure.js.map +1 -0
- package/dist/lint/rules/skipped-test-report.d.ts +11 -0
- package/dist/lint/rules/skipped-test-report.d.ts.map +1 -0
- package/dist/lint/rules/skipped-test-report.js +31 -0
- package/dist/lint/rules/skipped-test-report.js.map +1 -0
- package/dist/lint/rules/structure-rules.d.ts +67 -0
- package/dist/lint/rules/structure-rules.d.ts.map +1 -0
- package/dist/lint/rules/structure-rules.js +617 -0
- package/dist/lint/rules/structure-rules.js.map +1 -0
- package/dist/lint/rules/testdoc-japanese.d.ts +8 -0
- package/dist/lint/rules/testdoc-japanese.d.ts.map +1 -0
- package/dist/lint/rules/testdoc-japanese.js +31 -0
- package/dist/lint/rules/testdoc-japanese.js.map +1 -0
- package/dist/lint/rules/testdoc-min-length.d.ts +8 -0
- package/dist/lint/rules/testdoc-min-length.d.ts.map +1 -0
- package/dist/lint/rules/testdoc-min-length.js +31 -0
- package/dist/lint/rules/testdoc-min-length.js.map +1 -0
- package/dist/lint/rules/testdoc-required.d.ts +8 -0
- package/dist/lint/rules/testdoc-required.d.ts.map +1 -0
- package/dist/lint/rules/testdoc-required.js +27 -0
- package/dist/lint/rules/testdoc-required.js.map +1 -0
- package/dist/lint/rules/workflow-branch-naming.d.ts +20 -0
- package/dist/lint/rules/workflow-branch-naming.d.ts.map +1 -0
- package/dist/lint/rules/workflow-branch-naming.js +85 -0
- package/dist/lint/rules/workflow-branch-naming.js.map +1 -0
- package/dist/lint/rules/workflow-commit-format.d.ts +27 -0
- package/dist/lint/rules/workflow-commit-format.d.ts.map +1 -0
- package/dist/lint/rules/workflow-commit-format.js +92 -0
- package/dist/lint/rules/workflow-commit-format.js.map +1 -0
- package/dist/lint/rules/workflow-issue-fields.d.ts +24 -0
- package/dist/lint/rules/workflow-issue-fields.d.ts.map +1 -0
- package/dist/lint/rules/workflow-issue-fields.js +89 -0
- package/dist/lint/rules/workflow-issue-fields.js.map +1 -0
- package/dist/lint/rules/workflow-main-protection.d.ts +32 -0
- package/dist/lint/rules/workflow-main-protection.d.ts.map +1 -0
- package/dist/lint/rules/workflow-main-protection.js +114 -0
- package/dist/lint/rules/workflow-main-protection.js.map +1 -0
- package/dist/lint/structure-types.d.ts +216 -0
- package/dist/lint/structure-types.d.ts.map +1 -0
- package/dist/lint/structure-types.js +96 -0
- package/dist/lint/structure-types.js.map +1 -0
- package/dist/lint/types.d.ts +154 -0
- package/dist/lint/types.d.ts.map +1 -0
- package/dist/lint/types.js +21 -0
- package/dist/lint/types.js.map +1 -0
- package/dist/lint/workflow-types.d.ts +90 -0
- package/dist/lint/workflow-types.d.ts.map +1 -0
- package/dist/lint/workflow-types.js +7 -0
- package/dist/lint/workflow-types.js.map +1 -0
- package/dist/md/analyzer/index.d.ts +46 -0
- package/dist/md/analyzer/index.d.ts.map +1 -0
- package/dist/md/analyzer/index.js +288 -0
- package/dist/md/analyzer/index.js.map +1 -0
- package/dist/md/builder/index.d.ts +91 -0
- package/dist/md/builder/index.d.ts.map +1 -0
- package/dist/md/builder/index.js +446 -0
- package/dist/md/builder/index.js.map +1 -0
- package/dist/md/cli/analyze.d.ts +11 -0
- package/dist/md/cli/analyze.d.ts.map +1 -0
- package/dist/md/cli/analyze.js +118 -0
- package/dist/md/cli/analyze.js.map +1 -0
- package/dist/md/cli/build.d.ts +11 -0
- package/dist/md/cli/build.d.ts.map +1 -0
- package/dist/md/cli/build.js +74 -0
- package/dist/md/cli/build.js.map +1 -0
- package/dist/md/cli/extract.d.ts +25 -0
- package/dist/md/cli/extract.d.ts.map +1 -0
- package/dist/md/cli/extract.js +230 -0
- package/dist/md/cli/extract.js.map +1 -0
- package/dist/md/cli/index.d.ts +3 -0
- package/dist/md/cli/index.d.ts.map +1 -0
- package/dist/md/cli/index.js +99 -0
- package/dist/md/cli/index.js.map +1 -0
- package/dist/md/cli/lint.d.ts +11 -0
- package/dist/md/cli/lint.d.ts.map +1 -0
- package/dist/md/cli/lint.js +165 -0
- package/dist/md/cli/lint.js.map +1 -0
- package/dist/md/cli/list.d.ts +16 -0
- package/dist/md/cli/list.d.ts.map +1 -0
- package/dist/md/cli/list.js +85 -0
- package/dist/md/cli/list.js.map +1 -0
- package/dist/md/cli/program.d.ts +11 -0
- package/dist/md/cli/program.d.ts.map +1 -0
- package/dist/md/cli/program.js +104 -0
- package/dist/md/cli/program.js.map +1 -0
- package/dist/md/cli/validate.d.ts +8 -0
- package/dist/md/cli/validate.d.ts.map +1 -0
- package/dist/md/cli/validate.js +82 -0
- package/dist/md/cli/validate.js.map +1 -0
- package/dist/md/constants.d.ts +69 -0
- package/dist/md/constants.d.ts.map +1 -0
- package/dist/md/constants.js +69 -0
- package/dist/md/constants.js.map +1 -0
- package/dist/md/extractor/index.d.ts +57 -0
- package/dist/md/extractor/index.d.ts.map +1 -0
- package/dist/md/extractor/index.js +365 -0
- package/dist/md/extractor/index.js.map +1 -0
- package/dist/md/index.d.ts +26 -0
- package/dist/md/index.d.ts.map +1 -0
- package/dist/md/index.js +30 -0
- package/dist/md/index.js.map +1 -0
- package/dist/md/linter/index.d.ts +20 -0
- package/dist/md/linter/index.d.ts.map +1 -0
- package/dist/md/linter/index.js +421 -0
- package/dist/md/linter/index.js.map +1 -0
- package/dist/md/linter/token-optimizer.d.ts +66 -0
- package/dist/md/linter/token-optimizer.d.ts.map +1 -0
- package/dist/md/linter/token-optimizer.js +292 -0
- package/dist/md/linter/token-optimizer.js.map +1 -0
- package/dist/md/lister/index.d.ts +42 -0
- package/dist/md/lister/index.d.ts.map +1 -0
- package/dist/md/lister/index.js +317 -0
- package/dist/md/lister/index.js.map +1 -0
- package/dist/md/parser/heading-numbers.d.ts +43 -0
- package/dist/md/parser/heading-numbers.d.ts.map +1 -0
- package/dist/md/parser/heading-numbers.js +97 -0
- package/dist/md/parser/heading-numbers.js.map +1 -0
- package/dist/md/parser/section-meta.d.ts +50 -0
- package/dist/md/parser/section-meta.d.ts.map +1 -0
- package/dist/md/parser/section-meta.js +212 -0
- package/dist/md/parser/section-meta.js.map +1 -0
- package/dist/md/parser/template.d.ts +56 -0
- package/dist/md/parser/template.d.ts.map +1 -0
- package/dist/md/parser/template.js +122 -0
- package/dist/md/parser/template.js.map +1 -0
- package/dist/md/plugins/loader.d.ts +15 -0
- package/dist/md/plugins/loader.d.ts.map +1 -0
- package/dist/md/plugins/loader.js +80 -0
- package/dist/md/plugins/loader.js.map +1 -0
- package/dist/md/plugins/normalize-headings.d.ts +43 -0
- package/dist/md/plugins/normalize-headings.d.ts.map +1 -0
- package/dist/md/plugins/normalize-headings.js +51 -0
- package/dist/md/plugins/normalize-headings.js.map +1 -0
- package/dist/md/plugins/normalize-whitespace.d.ts +46 -0
- package/dist/md/plugins/normalize-whitespace.d.ts.map +1 -0
- package/dist/md/plugins/normalize-whitespace.js +86 -0
- package/dist/md/plugins/normalize-whitespace.js.map +1 -0
- package/dist/md/plugins/remove-badges.d.ts +36 -0
- package/dist/md/plugins/remove-badges.d.ts.map +1 -0
- package/dist/md/plugins/remove-badges.js +59 -0
- package/dist/md/plugins/remove-badges.js.map +1 -0
- package/dist/md/plugins/remove-comments.d.ts +27 -0
- package/dist/md/plugins/remove-comments.d.ts.map +1 -0
- package/dist/md/plugins/remove-comments.js +40 -0
- package/dist/md/plugins/remove-comments.js.map +1 -0
- package/dist/md/plugins/remove-duplicates.d.ts +40 -0
- package/dist/md/plugins/remove-duplicates.d.ts.map +1 -0
- package/dist/md/plugins/remove-duplicates.js +72 -0
- package/dist/md/plugins/remove-duplicates.js.map +1 -0
- package/dist/md/plugins/remove-internal-links.d.ts +38 -0
- package/dist/md/plugins/remove-internal-links.d.ts.map +1 -0
- package/dist/md/plugins/remove-internal-links.js +66 -0
- package/dist/md/plugins/remove-internal-links.js.map +1 -0
- package/dist/md/plugins/strip-heading-numbers.d.ts +35 -0
- package/dist/md/plugins/strip-heading-numbers.d.ts.map +1 -0
- package/dist/md/plugins/strip-heading-numbers.js +59 -0
- package/dist/md/plugins/strip-heading-numbers.js.map +1 -0
- package/dist/md/plugins/strip-section-meta.d.ts +37 -0
- package/dist/md/plugins/strip-section-meta.d.ts.map +1 -0
- package/dist/md/plugins/strip-section-meta.js +62 -0
- package/dist/md/plugins/strip-section-meta.js.map +1 -0
- package/dist/md/types/config.d.ts +260 -0
- package/dist/md/types/config.d.ts.map +1 -0
- package/dist/md/types/config.js +156 -0
- package/dist/md/types/config.js.map +1 -0
- package/dist/md/types/document.d.ts +37 -0
- package/dist/md/types/document.d.ts.map +1 -0
- package/dist/md/types/document.js +2 -0
- package/dist/md/types/document.js.map +1 -0
- package/dist/md/types/validation.d.ts +107 -0
- package/dist/md/types/validation.d.ts.map +1 -0
- package/dist/md/types/validation.js +2 -0
- package/dist/md/types/validation.js.map +1 -0
- package/dist/md/utils/code-blocks.d.ts +136 -0
- package/dist/md/utils/code-blocks.d.ts.map +1 -0
- package/dist/md/utils/code-blocks.js +178 -0
- package/dist/md/utils/code-blocks.js.map +1 -0
- package/dist/md/utils/config.d.ts +10 -0
- package/dist/md/utils/config.d.ts.map +1 -0
- package/dist/md/utils/config.js +99 -0
- package/dist/md/utils/config.js.map +1 -0
- package/dist/md/utils/file-collector.d.ts +78 -0
- package/dist/md/utils/file-collector.d.ts.map +1 -0
- package/dist/md/utils/file-collector.js +100 -0
- package/dist/md/utils/file-collector.js.map +1 -0
- package/dist/md/utils/markdown.d.ts +18 -0
- package/dist/md/utils/markdown.d.ts.map +1 -0
- package/dist/md/utils/markdown.js +93 -0
- package/dist/md/utils/markdown.js.map +1 -0
- package/dist/md/utils/remark.d.ts +91 -0
- package/dist/md/utils/remark.d.ts.map +1 -0
- package/dist/md/utils/remark.js +125 -0
- package/dist/md/utils/remark.js.map +1 -0
- package/dist/md/utils/tokens.d.ts +9 -0
- package/dist/md/utils/tokens.d.ts.map +1 -0
- package/dist/md/utils/tokens.js +31 -0
- package/dist/md/utils/tokens.js.map +1 -0
- package/dist/md/validator/index.d.ts +40 -0
- package/dist/md/validator/index.d.ts.map +1 -0
- package/dist/md/validator/index.js +299 -0
- package/dist/md/validator/index.js.map +1 -0
- package/dist/parsers/details-jsdoc.d.ts +42 -0
- package/dist/parsers/details-jsdoc.d.ts.map +1 -0
- package/dist/parsers/details-jsdoc.js +256 -0
- package/dist/parsers/details-jsdoc.js.map +1 -0
- package/dist/parsers/details-zod.d.ts +22 -0
- package/dist/parsers/details-zod.d.ts.map +1 -0
- package/dist/parsers/details-zod.js +146 -0
- package/dist/parsers/details-zod.js.map +1 -0
- package/dist/parsers/drizzle-schema.d.ts +92 -0
- package/dist/parsers/drizzle-schema.d.ts.map +1 -0
- package/dist/parsers/drizzle-schema.js +376 -0
- package/dist/parsers/drizzle-schema.js.map +1 -0
- package/dist/parsers/feature-map-tags.d.ts +45 -0
- package/dist/parsers/feature-map-tags.d.ts.map +1 -0
- package/dist/parsers/feature-map-tags.js +292 -0
- package/dist/parsers/feature-map-tags.js.map +1 -0
- package/dist/parsers/feature-map-type-extraction.d.ts +62 -0
- package/dist/parsers/feature-map-type-extraction.d.ts.map +1 -0
- package/dist/parsers/feature-map-type-extraction.js +347 -0
- package/dist/parsers/feature-map-type-extraction.js.map +1 -0
- package/dist/parsers/feature-map-utils.d.ts +34 -0
- package/dist/parsers/feature-map-utils.d.ts.map +1 -0
- package/dist/parsers/feature-map-utils.js +101 -0
- package/dist/parsers/feature-map-utils.js.map +1 -0
- package/dist/parsers/jsdoc-common.d.ts +209 -0
- package/dist/parsers/jsdoc-common.d.ts.map +1 -0
- package/dist/parsers/jsdoc-common.js +650 -0
- package/dist/parsers/jsdoc-common.js.map +1 -0
- package/dist/parsers/jsdoc.d.ts +76 -0
- package/dist/parsers/jsdoc.d.ts.map +1 -0
- package/dist/parsers/jsdoc.js +238 -0
- package/dist/parsers/jsdoc.js.map +1 -0
- package/dist/parsers/screenshot-annotations.d.ts +96 -0
- package/dist/parsers/screenshot-annotations.d.ts.map +1 -0
- package/dist/parsers/screenshot-annotations.js +227 -0
- package/dist/parsers/screenshot-annotations.js.map +1 -0
- package/dist/parsers/test-annotations.d.ts +46 -0
- package/dist/parsers/test-annotations.d.ts.map +1 -0
- package/dist/parsers/test-annotations.js +393 -0
- package/dist/parsers/test-annotations.js.map +1 -0
- package/dist/parsers/test-categorization.d.ts +42 -0
- package/dist/parsers/test-categorization.d.ts.map +1 -0
- package/dist/parsers/test-categorization.js +182 -0
- package/dist/parsers/test-categorization.js.map +1 -0
- package/dist/parsers/zod-schema.d.ts +105 -0
- package/dist/parsers/zod-schema.d.ts.map +1 -0
- package/dist/parsers/zod-schema.js +271 -0
- package/dist/parsers/zod-schema.js.map +1 -0
- package/dist/utils/action-inference.d.ts +23 -0
- package/dist/utils/action-inference.d.ts.map +1 -0
- package/dist/utils/action-inference.js +36 -0
- package/dist/utils/action-inference.js.map +1 -0
- package/dist/utils/app-inference.d.ts +31 -0
- package/dist/utils/app-inference.d.ts.map +1 -0
- package/dist/utils/app-inference.js +41 -0
- package/dist/utils/app-inference.js.map +1 -0
- package/dist/utils/auto-infer.d.ts +93 -0
- package/dist/utils/auto-infer.d.ts.map +1 -0
- package/dist/utils/auto-infer.js +184 -0
- package/dist/utils/auto-infer.js.map +1 -0
- package/dist/utils/config.d.ts +709 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +504 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/file.d.ts +46 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +103 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/formatters.d.ts +123 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +199 -0
- package/dist/utils/formatters.js.map +1 -0
- package/dist/utils/gh-config.d.ts +99 -0
- package/dist/utils/gh-config.d.ts.map +1 -0
- package/dist/utils/gh-config.js +247 -0
- package/dist/utils/gh-config.js.map +1 -0
- package/dist/utils/github.d.ts +108 -0
- package/dist/utils/github.d.ts.map +1 -0
- package/dist/utils/github.js +320 -0
- package/dist/utils/github.js.map +1 -0
- package/dist/utils/html.d.ts +107 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +376 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/i18n.d.ts +40 -0
- package/dist/utils/i18n.d.ts.map +1 -0
- package/dist/utils/i18n.js +148 -0
- package/dist/utils/i18n.js.map +1 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +49 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/project-fields.d.ts +71 -0
- package/dist/utils/project-fields.d.ts.map +1 -0
- package/dist/utils/project-fields.js +318 -0
- package/dist/utils/project-fields.js.map +1 -0
- package/dist/utils/repo-pairs.d.ts +94 -0
- package/dist/utils/repo-pairs.d.ts.map +1 -0
- package/dist/utils/repo-pairs.js +196 -0
- package/dist/utils/repo-pairs.js.map +1 -0
- package/dist/utils/route-inference.d.ts +81 -0
- package/dist/utils/route-inference.d.ts.map +1 -0
- package/dist/utils/route-inference.js +137 -0
- package/dist/utils/route-inference.js.map +1 -0
- package/dist/utils/sanitize.d.ts +27 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +38 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/utils/setup-check.d.ts +48 -0
- package/dist/utils/setup-check.d.ts.map +1 -0
- package/dist/utils/setup-check.js +226 -0
- package/dist/utils/setup-check.js.map +1 -0
- package/dist/utils/shirokumaignore.d.ts +55 -0
- package/dist/utils/shirokumaignore.d.ts.map +1 -0
- package/dist/utils/shirokumaignore.js +94 -0
- package/dist/utils/shirokumaignore.js.map +1 -0
- package/dist/utils/skills-repo.d.ts +353 -0
- package/dist/utils/skills-repo.d.ts.map +1 -0
- package/dist/utils/skills-repo.js +793 -0
- package/dist/utils/skills-repo.js.map +1 -0
- package/dist/utils/status-workflow.d.ts +54 -0
- package/dist/utils/status-workflow.d.ts.map +1 -0
- package/dist/utils/status-workflow.js +103 -0
- package/dist/utils/status-workflow.js.map +1 -0
- package/dist/validators/frontmatter.d.ts +41 -0
- package/dist/validators/frontmatter.d.ts.map +1 -0
- package/dist/validators/frontmatter.js +117 -0
- package/dist/validators/frontmatter.js.map +1 -0
- package/dist/validators/link-checker.d.ts +48 -0
- package/dist/validators/link-checker.d.ts.map +1 -0
- package/dist/validators/link-checker.js +108 -0
- package/dist/validators/link-checker.js.map +1 -0
- package/dist/validators/markdown-structure.d.ts +50 -0
- package/dist/validators/markdown-structure.d.ts.map +1 -0
- package/dist/validators/markdown-structure.js +253 -0
- package/dist/validators/markdown-structure.js.map +1 -0
- package/i18n/cli/en.json +164 -0
- package/i18n/cli/ja.json +164 -0
- package/i18n/discussion/en.json +191 -0
- package/i18n/discussion/ja.json +191 -0
- package/package.json +113 -0
- package/portal/app/api-tools/api-tools-client.tsx +411 -0
- package/portal/app/api-tools/api-tools-document.tsx +240 -0
- package/portal/app/api-tools/page.tsx +56 -0
- package/portal/app/api-tools/swagger-view.tsx +114 -0
- package/portal/app/apps/[appId]/[type]/[module]/[item]/item-tabs-client.tsx +71 -0
- package/portal/app/apps/[appId]/[type]/[module]/[item]/page.tsx +1422 -0
- package/portal/app/apps/[appId]/[type]/[module]/page.tsx +373 -0
- package/portal/app/apps/[appId]/feature-map/feature-map-app-document.tsx +298 -0
- package/portal/app/apps/[appId]/feature-map/page.tsx +224 -0
- package/portal/app/apps/[appId]/i18n/page.tsx +139 -0
- package/portal/app/apps/[appId]/test-cases/page.tsx +840 -0
- package/portal/app/apps/[appId]/tools/[tool]/page.tsx +351 -0
- package/portal/app/apps/[appId]/tools/api-tools-client.tsx +429 -0
- package/portal/app/apps/[appId]/tools/page.tsx +119 -0
- package/portal/app/db-schema/[db]/[table]/page.tsx +235 -0
- package/portal/app/db-schema/[db]/diagram/page.tsx +81 -0
- package/portal/app/db-schema/[db]/page.tsx +148 -0
- package/portal/app/db-schema/db-schema-document.tsx +100 -0
- package/portal/app/db-schema/diagram/client.tsx +211 -0
- package/portal/app/db-schema/diagram/page.tsx +20 -0
- package/portal/app/db-schema/page.tsx +145 -0
- package/portal/app/db-schema/table-detail-document.tsx +710 -0
- package/portal/app/db-schema/table-detail.tsx +747 -0
- package/portal/app/db-schema/table-list-document.tsx +224 -0
- package/portal/app/db-schema/table-list.tsx +247 -0
- package/portal/app/details/[type]/[module]/[item]/item-tabs-client.tsx +71 -0
- package/portal/app/details/[type]/[module]/[item]/page.tsx +1286 -0
- package/portal/app/details/[type]/[module]/page.tsx +884 -0
- package/portal/app/feature-map/feature-map-client.tsx +681 -0
- package/portal/app/feature-map/feature-map-document.tsx +313 -0
- package/portal/app/feature-map/page.tsx +438 -0
- package/portal/app/globals.css +205 -0
- package/portal/app/i18n/[...namespace]/page.tsx +190 -0
- package/portal/app/i18n/i18n-client.tsx +369 -0
- package/portal/app/i18n/page.tsx +339 -0
- package/portal/app/layout.tsx +37 -0
- package/portal/app/overview/page.tsx +65 -0
- package/portal/app/packages/[packageId]/page.tsx +201 -0
- package/portal/app/packages/page.tsx +148 -0
- package/portal/app/page.tsx +568 -0
- package/portal/app/test-cases/[file]/[line]/page.tsx +455 -0
- package/portal/app/test-cases/[file]/[line]/test-detail-document.tsx +335 -0
- package/portal/app/test-cases/[file]/page.tsx +323 -0
- package/portal/app/test-cases/[file]/test-file-document.tsx +335 -0
- package/portal/app/test-cases/page.tsx +546 -0
- package/portal/app/test-cases/test-cases-document.tsx +384 -0
- package/portal/components/code-block.tsx +57 -0
- package/portal/components/document/doc-params-table.tsx +71 -0
- package/portal/components/document/doc-section.tsx +133 -0
- package/portal/components/document/doc-table.tsx +119 -0
- package/portal/components/document/index.ts +9 -0
- package/portal/components/drawflow-er-diagram.tsx +607 -0
- package/portal/components/interactive-er-diagram.tsx +228 -0
- package/portal/components/layout/app-sidebar.tsx +490 -0
- package/portal/components/layout/er-sidebar.tsx +116 -0
- package/portal/components/layout/global-header.tsx +117 -0
- package/portal/components/layout/layout-content.tsx +48 -0
- package/portal/components/markdown-content.tsx +120 -0
- package/portal/components/mermaid-diagram.tsx +83 -0
- package/portal/components/reactflow-er-diagram.tsx +475 -0
- package/portal/components/search-dialog.tsx +268 -0
- package/portal/components/shared/coverage-score-bar.tsx +144 -0
- package/portal/components/swagger/endpoint-accordion.tsx +117 -0
- package/portal/components/swagger/index.ts +7 -0
- package/portal/components/swagger/method-badge.tsx +55 -0
- package/portal/components/swagger/params-table.tsx +78 -0
- package/portal/components/tabs-with-hash.tsx +43 -0
- package/portal/components/test/index.ts +2 -0
- package/portal/components/test/test-bdd-card.tsx +192 -0
- package/portal/components/test/test-matrix.tsx +242 -0
- package/portal/components/ui/accordion.tsx +66 -0
- package/portal/components/ui/badge.tsx +46 -0
- package/portal/components/ui/breadcrumb.tsx +109 -0
- package/portal/components/ui/button.tsx +62 -0
- package/portal/components/ui/card.tsx +92 -0
- package/portal/components/ui/collapsible.tsx +33 -0
- package/portal/components/ui/dialog.tsx +118 -0
- package/portal/components/ui/progress.tsx +28 -0
- package/portal/components/ui/scroll-area.tsx +58 -0
- package/portal/components/ui/sheet.tsx +139 -0
- package/portal/components/ui/table.tsx +116 -0
- package/portal/components/ui/tabs.tsx +66 -0
- package/portal/components.json +21 -0
- package/portal/lib/constants/test-categories.ts +186 -0
- package/portal/lib/data-loader.ts +1181 -0
- package/portal/lib/db-schema-utils.ts +182 -0
- package/portal/lib/format.ts +43 -0
- package/portal/lib/hooks/use-hash-tab.ts +144 -0
- package/portal/lib/path-utils.ts +25 -0
- package/portal/lib/search-index-generator.ts +214 -0
- package/portal/lib/search.ts +126 -0
- package/portal/lib/sidebar-context.tsx +111 -0
- package/portal/lib/types.ts +740 -0
- package/portal/lib/utils.ts +6 -0
- package/portal/next.config.ts +18 -0
- package/portal/package.json +45 -0
- package/portal/postcss.config.mjs +8 -0
- package/portal/tsconfig.json +42 -0
- package/portal/types/drawflow.d.ts +80 -0
- package/templates/README.md +73 -0
- package/templates/coverage.html +367 -0
- package/templates/dark-theme.css +443 -0
- package/templates/discussion/adr.yml.hbs +65 -0
- package/templates/discussion/handovers.yml.hbs +57 -0
- package/templates/discussion/knowledge.yml.hbs +60 -0
- package/templates/discussion/reports.yml.hbs +68 -0
- package/templates/discussion/research.yml.hbs +61 -0
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import { notFound } from "next/navigation";
|
|
3
|
+
import {
|
|
4
|
+
FlaskConical,
|
|
5
|
+
AlertTriangle,
|
|
6
|
+
CheckCircle2,
|
|
7
|
+
XCircle,
|
|
8
|
+
TrendingUp,
|
|
9
|
+
BarChart3,
|
|
10
|
+
Monitor,
|
|
11
|
+
Zap,
|
|
12
|
+
Component,
|
|
13
|
+
Database,
|
|
14
|
+
FileCode2,
|
|
15
|
+
ChevronRight,
|
|
16
|
+
ArrowLeft,
|
|
17
|
+
} from "lucide-react";
|
|
18
|
+
import {
|
|
19
|
+
loadTestCases,
|
|
20
|
+
loadApplications,
|
|
21
|
+
loadFeatureMap,
|
|
22
|
+
loadDetails,
|
|
23
|
+
loadCoverage,
|
|
24
|
+
type CoverageData,
|
|
25
|
+
} from "@/lib/data-loader";
|
|
26
|
+
import { encodeFilePath } from "@/lib/path-utils";
|
|
27
|
+
import {
|
|
28
|
+
Card,
|
|
29
|
+
CardHeader,
|
|
30
|
+
CardTitle,
|
|
31
|
+
CardDescription,
|
|
32
|
+
CardContent,
|
|
33
|
+
} from "@/components/ui/card";
|
|
34
|
+
import { Badge } from "@/components/ui/badge";
|
|
35
|
+
import { Progress } from "@/components/ui/progress";
|
|
36
|
+
import {
|
|
37
|
+
TabsWithHash,
|
|
38
|
+
TabsContent,
|
|
39
|
+
TabsList,
|
|
40
|
+
TabsTrigger,
|
|
41
|
+
} from "@/components/tabs-with-hash";
|
|
42
|
+
import type { TestCase, FeatureMapData, DetailsData } from "@/lib/types";
|
|
43
|
+
|
|
44
|
+
export const dynamic = "force-static";
|
|
45
|
+
|
|
46
|
+
interface PageProps {
|
|
47
|
+
params: Promise<{ appId: string }>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generate static params for all available apps
|
|
52
|
+
*/
|
|
53
|
+
export async function generateStaticParams() {
|
|
54
|
+
const applications = await loadApplications();
|
|
55
|
+
if (!applications?.apps) return [];
|
|
56
|
+
|
|
57
|
+
return applications.apps.map((app) => ({
|
|
58
|
+
appId: app.id,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get the source path prefixes for an app
|
|
64
|
+
*/
|
|
65
|
+
function getAppSourcePrefixes(appId: string, source?: string): string[] {
|
|
66
|
+
const defaults: Record<string, string[]> = {
|
|
67
|
+
admin: ["apps/admin", "tests/e2e/admin"],
|
|
68
|
+
public: ["apps/public", "tests/e2e/public"],
|
|
69
|
+
web: ["apps/web", "tests/e2e/web"],
|
|
70
|
+
mcp: ["apps/mcp", "tests/e2e/mcp"],
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (source) {
|
|
74
|
+
return [source, `tests/e2e/${appId}`];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return defaults[appId] || [`apps/${appId}`, `tests/e2e/${appId}`];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Filter test cases by app
|
|
82
|
+
*/
|
|
83
|
+
function filterTestCasesByApp(testCases: TestCase[], appId: string, sourcePrefixes: string[]): TestCase[] {
|
|
84
|
+
return testCases.filter((tc) => {
|
|
85
|
+
for (const prefix of sourcePrefixes) {
|
|
86
|
+
if (tc.file.startsWith(prefix)) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (tc.app === appId) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Strip matching prefix from file path for display
|
|
99
|
+
*/
|
|
100
|
+
function stripMatchingPrefix(file: string, prefixes: string[]): string {
|
|
101
|
+
for (const prefix of prefixes) {
|
|
102
|
+
if (file.startsWith(prefix + "/")) {
|
|
103
|
+
return file.replace(prefix + "/", "");
|
|
104
|
+
}
|
|
105
|
+
if (file.startsWith(prefix)) {
|
|
106
|
+
return file.replace(prefix, "");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return file;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Group test cases by file
|
|
114
|
+
*/
|
|
115
|
+
function groupTestCasesByFile(testCases: TestCase[]): Record<string, TestCase[]> {
|
|
116
|
+
const grouped: Record<string, TestCase[]> = {};
|
|
117
|
+
for (const tc of testCases) {
|
|
118
|
+
if (!grouped[tc.file]) grouped[tc.file] = [];
|
|
119
|
+
grouped[tc.file].push(tc);
|
|
120
|
+
}
|
|
121
|
+
return grouped;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get category breakdown
|
|
126
|
+
*/
|
|
127
|
+
function getCategoryBreakdown(testCases: TestCase[]): Record<string, number> {
|
|
128
|
+
const breakdown: Record<string, number> = {};
|
|
129
|
+
for (const tc of testCases) {
|
|
130
|
+
const cat = tc.category || "unknown";
|
|
131
|
+
breakdown[cat] = (breakdown[cat] || 0) + 1;
|
|
132
|
+
}
|
|
133
|
+
return breakdown;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Test category labels
|
|
137
|
+
const testCategoryLabels: Record<string, { ja: string; color: string }> = {
|
|
138
|
+
"happy-path": { ja: "正常系", color: "bg-green-500" },
|
|
139
|
+
auth: { ja: "認証", color: "bg-blue-500" },
|
|
140
|
+
"error-handling": { ja: "異常系", color: "bg-red-500" },
|
|
141
|
+
validation: { ja: "バリデーション", color: "bg-yellow-500" },
|
|
142
|
+
"edge-case": { ja: "境界値", color: "bg-purple-500" },
|
|
143
|
+
integration: { ja: "統合", color: "bg-cyan-500" },
|
|
144
|
+
other: { ja: "その他", color: "bg-gray-500" },
|
|
145
|
+
success: { ja: "正常系", color: "bg-green-500" },
|
|
146
|
+
error: { ja: "異常系", color: "bg-red-500" },
|
|
147
|
+
edge: { ja: "境界値", color: "bg-purple-500" },
|
|
148
|
+
unknown: { ja: "その他", color: "bg-gray-500" },
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Item type config
|
|
152
|
+
const itemTypeConfig: Record<string, { icon: React.ElementType; label: string; labelJa: string }> = {
|
|
153
|
+
screens: { icon: Monitor, label: "Screens", labelJa: "画面" },
|
|
154
|
+
components: { icon: Component, label: "Components", labelJa: "コンポーネント" },
|
|
155
|
+
actions: { icon: Zap, label: "Actions", labelJa: "アクション" },
|
|
156
|
+
tables: { icon: Database, label: "Tables", labelJa: "テーブル" },
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Filter feature map items by app
|
|
161
|
+
*/
|
|
162
|
+
function filterFeatureMapByApp(featureMap: FeatureMapData | null, appId: string): FeatureMapData | null {
|
|
163
|
+
if (!featureMap) return null;
|
|
164
|
+
|
|
165
|
+
// Map appId to app names in feature map
|
|
166
|
+
// Note: appId "mcp" maps to items with app="API" or app="MCP" (for backward compatibility)
|
|
167
|
+
const appNameMap: Record<string, string[]> = {
|
|
168
|
+
admin: ["Admin"],
|
|
169
|
+
public: ["Public"],
|
|
170
|
+
web: ["Web"],
|
|
171
|
+
mcp: ["API", "MCP"], // Support both new "API" and legacy "MCP"
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const appNames = appNameMap[appId] || [appId];
|
|
175
|
+
const filteredFeatures: FeatureMapData["features"] = {};
|
|
176
|
+
|
|
177
|
+
for (const [moduleName, group] of Object.entries(featureMap.features)) {
|
|
178
|
+
// Check if any item in the group belongs to this app
|
|
179
|
+
const allItems = [
|
|
180
|
+
...(group.screens || []),
|
|
181
|
+
...(group.components || []),
|
|
182
|
+
...(group.actions || []),
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
// Get app from first item that has it
|
|
186
|
+
const firstItemWithApp = allItems.find(item => item.app);
|
|
187
|
+
const moduleApp = firstItemWithApp?.app || "";
|
|
188
|
+
|
|
189
|
+
if (appNames.some(name => moduleApp.toLowerCase().includes(name.toLowerCase()))) {
|
|
190
|
+
filteredFeatures[moduleName] = group;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
...featureMap,
|
|
196
|
+
features: filteredFeatures,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Calculate coverage by mapping coverage.json to feature-map items
|
|
202
|
+
* Feature-map items are considered "covered" if their source path is covered in coverage.json
|
|
203
|
+
*/
|
|
204
|
+
function calculateFeatureMapCoverage(
|
|
205
|
+
coverage: CoverageData | null,
|
|
206
|
+
featureMap: FeatureMapData | null,
|
|
207
|
+
appId: string
|
|
208
|
+
): { totalItems: number; testedItems: number; coveragePercent: number; missingCount: number } | null {
|
|
209
|
+
const filteredMap = filterFeatureMapByApp(featureMap, appId);
|
|
210
|
+
if (!coverage || !filteredMap) return null;
|
|
211
|
+
|
|
212
|
+
// Build a set of covered source paths
|
|
213
|
+
const coveredSources = new Set<string>();
|
|
214
|
+
for (const result of coverage.results) {
|
|
215
|
+
if (result.status === "covered" || result.status === "skipped") {
|
|
216
|
+
coveredSources.add(result.source);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let totalItems = 0;
|
|
221
|
+
let testedItems = 0;
|
|
222
|
+
|
|
223
|
+
// Check each feature-map item against covered sources
|
|
224
|
+
for (const group of Object.values(filteredMap.features)) {
|
|
225
|
+
const items = [
|
|
226
|
+
...(group.screens || []),
|
|
227
|
+
...(group.components || []),
|
|
228
|
+
...(group.actions || []),
|
|
229
|
+
];
|
|
230
|
+
|
|
231
|
+
for (const item of items) {
|
|
232
|
+
totalItems++;
|
|
233
|
+
// Check if item's path matches any covered source
|
|
234
|
+
if ("path" in item && item.path) {
|
|
235
|
+
if (coveredSources.has(item.path)) {
|
|
236
|
+
testedItems++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (totalItems === 0) return null;
|
|
243
|
+
|
|
244
|
+
const missingCount = totalItems - testedItems;
|
|
245
|
+
const coveragePercent = Math.round((testedItems / totalItems) * 100);
|
|
246
|
+
|
|
247
|
+
return { totalItems, testedItems, coveragePercent, missingCount };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get coverage gaps for an app
|
|
252
|
+
*/
|
|
253
|
+
function getCoverageGaps(
|
|
254
|
+
featureMap: FeatureMapData | null,
|
|
255
|
+
details: DetailsData | null,
|
|
256
|
+
appId: string
|
|
257
|
+
): Array<{ type: string; module: string; name: string; path?: string }> {
|
|
258
|
+
const filteredMap = filterFeatureMapByApp(featureMap, appId);
|
|
259
|
+
if (!filteredMap || !details) return [];
|
|
260
|
+
|
|
261
|
+
const gaps: Array<{ type: string; module: string; name: string; path?: string }> = [];
|
|
262
|
+
|
|
263
|
+
for (const [moduleName, group] of Object.entries(filteredMap.features)) {
|
|
264
|
+
const itemTypes = [
|
|
265
|
+
{ type: "screens", items: group.screens || [] },
|
|
266
|
+
{ type: "components", items: group.components || [] },
|
|
267
|
+
{ type: "actions", items: group.actions || [] },
|
|
268
|
+
{ type: "tables", items: group.tables || [] },
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
for (const { type, items } of itemTypes) {
|
|
272
|
+
for (const item of items) {
|
|
273
|
+
const possibleKeys = [`${type}/${moduleName}/${item.name}`];
|
|
274
|
+
|
|
275
|
+
if ("path" in item && item.path) {
|
|
276
|
+
const fileName = item.path.split("/").pop()?.replace(/\.(ts|tsx)$/, "");
|
|
277
|
+
if (fileName) {
|
|
278
|
+
possibleKeys.unshift(`${type}/${fileName}/${item.name}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
let hasTest = false;
|
|
283
|
+
for (const key of possibleKeys) {
|
|
284
|
+
const detail = details.details[key];
|
|
285
|
+
if (detail?.testCoverage?.hasTest) {
|
|
286
|
+
hasTest = true;
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (!hasTest) {
|
|
292
|
+
gaps.push({
|
|
293
|
+
type,
|
|
294
|
+
module: moduleName,
|
|
295
|
+
name: item.name,
|
|
296
|
+
path: "path" in item ? item.path : undefined,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return gaps;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Get coverage distribution for an app
|
|
308
|
+
*/
|
|
309
|
+
function getCoverageDistribution(
|
|
310
|
+
details: DetailsData | null,
|
|
311
|
+
featureMap: FeatureMapData | null,
|
|
312
|
+
appId: string
|
|
313
|
+
): { high: number; medium: number; low: number; none: number } {
|
|
314
|
+
const filteredMap = filterFeatureMapByApp(featureMap, appId);
|
|
315
|
+
if (!details || !filteredMap) return { high: 0, medium: 0, low: 0, none: 0 };
|
|
316
|
+
|
|
317
|
+
let high = 0, medium = 0, low = 0, none = 0;
|
|
318
|
+
|
|
319
|
+
// Get item names from filtered feature map
|
|
320
|
+
const itemNames = new Set<string>();
|
|
321
|
+
for (const group of Object.values(filteredMap.features)) {
|
|
322
|
+
for (const item of [...(group.screens || []), ...(group.components || []), ...(group.actions || [])]) {
|
|
323
|
+
itemNames.add(item.name);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
for (const [key, item] of Object.entries(details.details)) {
|
|
328
|
+
// Check if this item belongs to the app
|
|
329
|
+
const itemName = key.split("/").pop() || "";
|
|
330
|
+
if (!itemNames.has(itemName)) continue;
|
|
331
|
+
|
|
332
|
+
if (!item.testCoverage?.hasTest) {
|
|
333
|
+
none++;
|
|
334
|
+
} else {
|
|
335
|
+
const score = item.testCoverage.coverageScore;
|
|
336
|
+
if (score >= 70) high++;
|
|
337
|
+
else if (score >= 40) medium++;
|
|
338
|
+
else low++;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return { high, medium, low, none };
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Get overall stats for an app
|
|
347
|
+
*/
|
|
348
|
+
function getOverallStats(
|
|
349
|
+
featureMap: FeatureMapData | null,
|
|
350
|
+
details: DetailsData | null,
|
|
351
|
+
appId: string
|
|
352
|
+
): { totalItems: number; testedItems: number; coveragePercent: number } {
|
|
353
|
+
const filteredMap = filterFeatureMapByApp(featureMap, appId);
|
|
354
|
+
if (!filteredMap || !details) return { totalItems: 0, testedItems: 0, coveragePercent: 0 };
|
|
355
|
+
|
|
356
|
+
let totalItems = 0;
|
|
357
|
+
let testedItems = 0;
|
|
358
|
+
|
|
359
|
+
for (const group of Object.values(filteredMap.features)) {
|
|
360
|
+
const items = [
|
|
361
|
+
...(group.screens || []),
|
|
362
|
+
...(group.components || []),
|
|
363
|
+
...(group.actions || []),
|
|
364
|
+
...(group.tables || []),
|
|
365
|
+
];
|
|
366
|
+
totalItems += items.length;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Count tested items from details
|
|
370
|
+
const itemNames = new Set<string>();
|
|
371
|
+
for (const group of Object.values(filteredMap.features)) {
|
|
372
|
+
for (const item of [...(group.screens || []), ...(group.components || []), ...(group.actions || []), ...(group.tables || [])]) {
|
|
373
|
+
itemNames.add(item.name);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
for (const [key, item] of Object.entries(details.details)) {
|
|
378
|
+
const itemName = key.split("/").pop() || "";
|
|
379
|
+
if (itemNames.has(itemName) && item.testCoverage?.hasTest) {
|
|
380
|
+
testedItems++;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
totalItems,
|
|
386
|
+
testedItems,
|
|
387
|
+
coveragePercent: totalItems > 0 ? Math.round((testedItems / totalItems) * 100) : 0,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Analyze test quality balance
|
|
393
|
+
*/
|
|
394
|
+
function analyzeTestQuality(categoryBreakdown: Record<string, number>, totalTests: number): {
|
|
395
|
+
status: "good" | "warning" | "poor";
|
|
396
|
+
message: string;
|
|
397
|
+
details: string[];
|
|
398
|
+
} {
|
|
399
|
+
if (totalTests === 0) return { status: "poor", message: "テストがありません", details: [] };
|
|
400
|
+
|
|
401
|
+
const details: string[] = [];
|
|
402
|
+
const successRatio = (categoryBreakdown["happy-path"] || 0) / totalTests;
|
|
403
|
+
const errorRatio = (categoryBreakdown["error-handling"] || 0) / totalTests;
|
|
404
|
+
const validationRatio = (categoryBreakdown.validation || 0) / totalTests;
|
|
405
|
+
|
|
406
|
+
if (successRatio > 0.7) {
|
|
407
|
+
details.push("正常系テストが多すぎます(異常系・バリデーションも追加推奨)");
|
|
408
|
+
}
|
|
409
|
+
if (errorRatio < 0.1 && totalTests > 10) {
|
|
410
|
+
details.push("異常系テストが少ないです");
|
|
411
|
+
}
|
|
412
|
+
if (validationRatio < 0.05 && totalTests > 10) {
|
|
413
|
+
details.push("バリデーションテストが少ないです");
|
|
414
|
+
}
|
|
415
|
+
if ((categoryBreakdown["edge-case"] || 0) === 0 && totalTests > 20) {
|
|
416
|
+
details.push("境界値テストがありません");
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (details.length === 0) {
|
|
420
|
+
return { status: "good", message: "テストカテゴリのバランスが良好です", details: [] };
|
|
421
|
+
} else if (details.length <= 2) {
|
|
422
|
+
return { status: "warning", message: "改善の余地があります", details };
|
|
423
|
+
} else {
|
|
424
|
+
return { status: "poor", message: "テストバランスの改善が必要です", details };
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export default async function AppTestCasesPage({ params }: PageProps) {
|
|
429
|
+
const { appId } = await params;
|
|
430
|
+
|
|
431
|
+
const [data, applications, featureMap, details, coverage] = await Promise.all([
|
|
432
|
+
loadTestCases(),
|
|
433
|
+
loadApplications(),
|
|
434
|
+
loadFeatureMap(),
|
|
435
|
+
loadDetails(),
|
|
436
|
+
loadCoverage(),
|
|
437
|
+
]);
|
|
438
|
+
|
|
439
|
+
// Find the app configuration
|
|
440
|
+
const app = applications?.apps?.find((a) => a.id === appId);
|
|
441
|
+
if (!app) {
|
|
442
|
+
notFound();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (!data) {
|
|
446
|
+
return (
|
|
447
|
+
<div className="space-y-8">
|
|
448
|
+
<header>
|
|
449
|
+
<h1 className="text-3xl font-bold tracking-tight">Test Cases - {app.name}</h1>
|
|
450
|
+
<p className="mt-2 text-destructive">No test cases data available.</p>
|
|
451
|
+
</header>
|
|
452
|
+
</div>
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Filter test cases by app
|
|
457
|
+
const sourcePrefixes = getAppSourcePrefixes(appId, app.source);
|
|
458
|
+
const filteredTestCases = filterTestCasesByApp(data.testCases, appId, sourcePrefixes);
|
|
459
|
+
const groupedByFile = groupTestCasesByFile(filteredTestCases);
|
|
460
|
+
const categoryBreakdown = getCategoryBreakdown(filteredTestCases);
|
|
461
|
+
|
|
462
|
+
// Count files
|
|
463
|
+
const fileCount = Object.keys(groupedByFile).length;
|
|
464
|
+
|
|
465
|
+
// Count by framework
|
|
466
|
+
const jestCount = filteredTestCases.filter((tc) => tc.framework === "jest").length;
|
|
467
|
+
const playwrightCount = filteredTestCases.filter((tc) => tc.framework === "playwright").length;
|
|
468
|
+
|
|
469
|
+
// Coverage analysis - map coverage.json to feature-map items
|
|
470
|
+
const coverageGaps = getCoverageGaps(featureMap, details, appId);
|
|
471
|
+
const coverageDistribution = getCoverageDistribution(details, featureMap, appId);
|
|
472
|
+
const appCoverage = calculateFeatureMapCoverage(coverage, featureMap, appId);
|
|
473
|
+
const overallStats = appCoverage || getOverallStats(featureMap, details, appId);
|
|
474
|
+
const qualityAnalysis = analyzeTestQuality(categoryBreakdown, filteredTestCases.length);
|
|
475
|
+
|
|
476
|
+
// Group gaps by type
|
|
477
|
+
const gapsByType = coverageGaps.reduce((acc, gap) => {
|
|
478
|
+
if (!acc[gap.type]) acc[gap.type] = [];
|
|
479
|
+
acc[gap.type].push(gap);
|
|
480
|
+
return acc;
|
|
481
|
+
}, {} as Record<string, typeof coverageGaps>);
|
|
482
|
+
|
|
483
|
+
// Get app color
|
|
484
|
+
const colorClass = app.color === "blue" ? "text-blue-500 bg-blue-500/10" :
|
|
485
|
+
app.color === "green" ? "text-green-500 bg-green-500/10" :
|
|
486
|
+
app.color === "purple" ? "text-purple-500 bg-purple-500/10" :
|
|
487
|
+
"text-gray-500 bg-gray-500/10";
|
|
488
|
+
|
|
489
|
+
return (
|
|
490
|
+
<div className="space-y-8">
|
|
491
|
+
{/* Breadcrumb */}
|
|
492
|
+
<nav className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
493
|
+
<Link href="/" className="hover:text-foreground">
|
|
494
|
+
Home
|
|
495
|
+
</Link>
|
|
496
|
+
<span>/</span>
|
|
497
|
+
<Link href="/test-cases" className="hover:text-foreground">
|
|
498
|
+
Test Cases
|
|
499
|
+
</Link>
|
|
500
|
+
<span>/</span>
|
|
501
|
+
<span className="text-foreground">{app.name}</span>
|
|
502
|
+
</nav>
|
|
503
|
+
|
|
504
|
+
{/* Header */}
|
|
505
|
+
<header>
|
|
506
|
+
<div className="flex items-center justify-between">
|
|
507
|
+
<div className="flex items-center gap-3">
|
|
508
|
+
<div className={`rounded-lg p-2 ${colorClass}`}>
|
|
509
|
+
<FlaskConical className="h-6 w-6" />
|
|
510
|
+
</div>
|
|
511
|
+
<div>
|
|
512
|
+
<h1 className="text-3xl font-bold tracking-tight">Test Quality Dashboard - {app.name}</h1>
|
|
513
|
+
<p className="mt-1 text-muted-foreground">
|
|
514
|
+
{app.description || `${app.name} のテストカバレッジと品質メトリクス`}
|
|
515
|
+
</p>
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
<Link
|
|
519
|
+
href="/test-cases"
|
|
520
|
+
className="flex items-center gap-2 rounded-lg border border-border bg-card px-4 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
|
|
521
|
+
>
|
|
522
|
+
<ArrowLeft className="h-4 w-4" />
|
|
523
|
+
全体ビュー
|
|
524
|
+
</Link>
|
|
525
|
+
</div>
|
|
526
|
+
</header>
|
|
527
|
+
|
|
528
|
+
{/* Tabbed Content */}
|
|
529
|
+
<TabsWithHash defaultValue="overview" className="w-full">
|
|
530
|
+
<TabsList className="grid w-full grid-cols-3">
|
|
531
|
+
<TabsTrigger value="overview" className="flex items-center gap-2">
|
|
532
|
+
<BarChart3 className="h-4 w-4" />
|
|
533
|
+
概要
|
|
534
|
+
</TabsTrigger>
|
|
535
|
+
<TabsTrigger value="files" className="flex items-center gap-2">
|
|
536
|
+
<FileCode2 className="h-4 w-4" />
|
|
537
|
+
テストファイル
|
|
538
|
+
<Badge variant="secondary" className="text-xs">
|
|
539
|
+
{fileCount}
|
|
540
|
+
</Badge>
|
|
541
|
+
</TabsTrigger>
|
|
542
|
+
<TabsTrigger value="gaps" className="flex items-center gap-2">
|
|
543
|
+
<AlertTriangle className="h-4 w-4" />
|
|
544
|
+
ギャップ
|
|
545
|
+
<Badge variant="secondary" className="text-xs bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400">
|
|
546
|
+
{coverageGaps.length}
|
|
547
|
+
</Badge>
|
|
548
|
+
</TabsTrigger>
|
|
549
|
+
</TabsList>
|
|
550
|
+
|
|
551
|
+
{/* Overview Tab */}
|
|
552
|
+
<TabsContent value="overview" className="mt-4 space-y-6">
|
|
553
|
+
{/* Stats Cards */}
|
|
554
|
+
<div className="grid gap-4 md:grid-cols-4">
|
|
555
|
+
<Card>
|
|
556
|
+
<CardHeader className="pb-2">
|
|
557
|
+
<CardDescription>総テスト数</CardDescription>
|
|
558
|
+
<CardTitle className="text-3xl">{filteredTestCases.length}</CardTitle>
|
|
559
|
+
</CardHeader>
|
|
560
|
+
<CardContent>
|
|
561
|
+
<div className="flex flex-col gap-1 text-xs text-muted-foreground">
|
|
562
|
+
<div className="flex gap-2">
|
|
563
|
+
<span>Jest: {jestCount}</span>
|
|
564
|
+
<span>|</span>
|
|
565
|
+
<span>Playwright: {playwrightCount}</span>
|
|
566
|
+
</div>
|
|
567
|
+
</div>
|
|
568
|
+
</CardContent>
|
|
569
|
+
</Card>
|
|
570
|
+
|
|
571
|
+
<Card>
|
|
572
|
+
<CardHeader className="pb-2">
|
|
573
|
+
<CardDescription>カバレッジ率</CardDescription>
|
|
574
|
+
<CardTitle className="text-3xl">{overallStats.coveragePercent}%</CardTitle>
|
|
575
|
+
</CardHeader>
|
|
576
|
+
<CardContent>
|
|
577
|
+
<Progress value={overallStats.coveragePercent} className="h-2" />
|
|
578
|
+
<p className="mt-1 text-xs text-muted-foreground">
|
|
579
|
+
{overallStats.testedItems} / {overallStats.totalItems} items
|
|
580
|
+
</p>
|
|
581
|
+
</CardContent>
|
|
582
|
+
</Card>
|
|
583
|
+
|
|
584
|
+
<Card>
|
|
585
|
+
<CardHeader className="pb-2">
|
|
586
|
+
<CardDescription>テスト無し</CardDescription>
|
|
587
|
+
<CardTitle className="text-3xl text-red-500">{coverageGaps.length}</CardTitle>
|
|
588
|
+
</CardHeader>
|
|
589
|
+
<CardContent>
|
|
590
|
+
<p className="text-xs text-muted-foreground">
|
|
591
|
+
カバレッジギャップ
|
|
592
|
+
</p>
|
|
593
|
+
</CardContent>
|
|
594
|
+
</Card>
|
|
595
|
+
|
|
596
|
+
<Card className={qualityAnalysis.status === "good" ? "border-green-500/50" : qualityAnalysis.status === "warning" ? "border-yellow-500/50" : "border-red-500/50"}>
|
|
597
|
+
<CardHeader className="pb-2">
|
|
598
|
+
<CardDescription>品質スコア</CardDescription>
|
|
599
|
+
<CardTitle className="flex items-center gap-2">
|
|
600
|
+
{qualityAnalysis.status === "good" ? (
|
|
601
|
+
<CheckCircle2 className="h-6 w-6 text-green-500" />
|
|
602
|
+
) : qualityAnalysis.status === "warning" ? (
|
|
603
|
+
<AlertTriangle className="h-6 w-6 text-yellow-500" />
|
|
604
|
+
) : (
|
|
605
|
+
<XCircle className="h-6 w-6 text-red-500" />
|
|
606
|
+
)}
|
|
607
|
+
<span className="text-lg">{qualityAnalysis.message}</span>
|
|
608
|
+
</CardTitle>
|
|
609
|
+
</CardHeader>
|
|
610
|
+
{qualityAnalysis.details.length > 0 && (
|
|
611
|
+
<CardContent>
|
|
612
|
+
<ul className="text-xs text-muted-foreground space-y-1">
|
|
613
|
+
{qualityAnalysis.details.map((d, i) => (
|
|
614
|
+
<li key={i}>• {d}</li>
|
|
615
|
+
))}
|
|
616
|
+
</ul>
|
|
617
|
+
</CardContent>
|
|
618
|
+
)}
|
|
619
|
+
</Card>
|
|
620
|
+
</div>
|
|
621
|
+
|
|
622
|
+
{/* Two Column Layout */}
|
|
623
|
+
<div className="grid gap-6 lg:grid-cols-2">
|
|
624
|
+
{/* Test Category Distribution */}
|
|
625
|
+
<Card>
|
|
626
|
+
<CardHeader>
|
|
627
|
+
<div className="flex items-center gap-2">
|
|
628
|
+
<BarChart3 className="h-5 w-5 text-muted-foreground" />
|
|
629
|
+
<CardTitle>テストカテゴリ分布</CardTitle>
|
|
630
|
+
</div>
|
|
631
|
+
<CardDescription>
|
|
632
|
+
テストの種類別内訳
|
|
633
|
+
</CardDescription>
|
|
634
|
+
</CardHeader>
|
|
635
|
+
<CardContent className="space-y-4">
|
|
636
|
+
{Object.entries(categoryBreakdown)
|
|
637
|
+
.filter(([_, count]) => count > 0)
|
|
638
|
+
.sort((a, b) => b[1] - a[1])
|
|
639
|
+
.map(([category, count]) => {
|
|
640
|
+
const config = testCategoryLabels[category] || testCategoryLabels.unknown;
|
|
641
|
+
const percentage = Math.round((count / filteredTestCases.length) * 100);
|
|
642
|
+
return (
|
|
643
|
+
<div key={category} className="space-y-1">
|
|
644
|
+
<div className="flex items-center justify-between text-sm">
|
|
645
|
+
<div className="flex items-center gap-2">
|
|
646
|
+
<div className={`h-3 w-3 rounded-full ${config.color}`} />
|
|
647
|
+
<span>{config.ja}</span>
|
|
648
|
+
</div>
|
|
649
|
+
<span className="text-muted-foreground">{count} ({percentage}%)</span>
|
|
650
|
+
</div>
|
|
651
|
+
<Progress value={percentage} className="h-2" />
|
|
652
|
+
</div>
|
|
653
|
+
);
|
|
654
|
+
})}
|
|
655
|
+
</CardContent>
|
|
656
|
+
</Card>
|
|
657
|
+
|
|
658
|
+
{/* Coverage Score Distribution */}
|
|
659
|
+
<Card>
|
|
660
|
+
<CardHeader>
|
|
661
|
+
<div className="flex items-center gap-2">
|
|
662
|
+
<TrendingUp className="h-5 w-5 text-muted-foreground" />
|
|
663
|
+
<CardTitle>カバレッジスコア分布</CardTitle>
|
|
664
|
+
</div>
|
|
665
|
+
<CardDescription>
|
|
666
|
+
機能別テストカバレッジの品質
|
|
667
|
+
</CardDescription>
|
|
668
|
+
</CardHeader>
|
|
669
|
+
<CardContent className="space-y-4">
|
|
670
|
+
<div className="space-y-3">
|
|
671
|
+
<div className="flex items-center justify-between">
|
|
672
|
+
<div className="flex items-center gap-2">
|
|
673
|
+
<div className="h-3 w-3 rounded-full bg-green-500" />
|
|
674
|
+
<span className="text-sm">高 (70%+)</span>
|
|
675
|
+
</div>
|
|
676
|
+
<Badge variant="secondary" className="bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400">
|
|
677
|
+
{coverageDistribution.high}
|
|
678
|
+
</Badge>
|
|
679
|
+
</div>
|
|
680
|
+
<div className="flex items-center justify-between">
|
|
681
|
+
<div className="flex items-center gap-2">
|
|
682
|
+
<div className="h-3 w-3 rounded-full bg-yellow-500" />
|
|
683
|
+
<span className="text-sm">中 (40-69%)</span>
|
|
684
|
+
</div>
|
|
685
|
+
<Badge variant="secondary" className="bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400">
|
|
686
|
+
{coverageDistribution.medium}
|
|
687
|
+
</Badge>
|
|
688
|
+
</div>
|
|
689
|
+
<div className="flex items-center justify-between">
|
|
690
|
+
<div className="flex items-center gap-2">
|
|
691
|
+
<div className="h-3 w-3 rounded-full bg-red-500" />
|
|
692
|
+
<span className="text-sm">低 (1-39%)</span>
|
|
693
|
+
</div>
|
|
694
|
+
<Badge variant="secondary" className="bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400">
|
|
695
|
+
{coverageDistribution.low}
|
|
696
|
+
</Badge>
|
|
697
|
+
</div>
|
|
698
|
+
<div className="flex items-center justify-between">
|
|
699
|
+
<div className="flex items-center gap-2">
|
|
700
|
+
<div className="h-3 w-3 rounded-full bg-gray-400" />
|
|
701
|
+
<span className="text-sm">なし (0%)</span>
|
|
702
|
+
</div>
|
|
703
|
+
<Badge variant="secondary">
|
|
704
|
+
{coverageDistribution.none}
|
|
705
|
+
</Badge>
|
|
706
|
+
</div>
|
|
707
|
+
</div>
|
|
708
|
+
</CardContent>
|
|
709
|
+
</Card>
|
|
710
|
+
</div>
|
|
711
|
+
</TabsContent>
|
|
712
|
+
|
|
713
|
+
{/* Test Files Tab */}
|
|
714
|
+
<TabsContent value="files" className="mt-4">
|
|
715
|
+
<Card>
|
|
716
|
+
<CardHeader>
|
|
717
|
+
<div className="flex items-center gap-2">
|
|
718
|
+
<FileCode2 className="h-5 w-5 text-muted-foreground" />
|
|
719
|
+
<CardTitle>テストファイル</CardTitle>
|
|
720
|
+
</div>
|
|
721
|
+
<CardDescription>
|
|
722
|
+
{fileCount} ファイル / {filteredTestCases.length} テスト
|
|
723
|
+
</CardDescription>
|
|
724
|
+
</CardHeader>
|
|
725
|
+
<CardContent>
|
|
726
|
+
<div className="space-y-4">
|
|
727
|
+
{Object.entries(groupedByFile)
|
|
728
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
729
|
+
.map(([file, tests]) => (
|
|
730
|
+
<div
|
|
731
|
+
key={file}
|
|
732
|
+
className="rounded-lg border border-border p-4 hover:bg-muted/50 transition-colors"
|
|
733
|
+
>
|
|
734
|
+
<div className="flex items-center justify-between">
|
|
735
|
+
<Link
|
|
736
|
+
href={`/test-cases/${encodeFilePath(file)}`}
|
|
737
|
+
className="flex items-center gap-2 font-medium text-foreground hover:text-primary"
|
|
738
|
+
>
|
|
739
|
+
<FileCode2 className="h-4 w-4 text-muted-foreground" />
|
|
740
|
+
<span className="truncate">{stripMatchingPrefix(file, sourcePrefixes)}</span>
|
|
741
|
+
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
|
742
|
+
</Link>
|
|
743
|
+
<Badge variant="secondary">{tests.length} tests</Badge>
|
|
744
|
+
</div>
|
|
745
|
+
<div className="mt-2 flex flex-wrap gap-1">
|
|
746
|
+
{(() => {
|
|
747
|
+
const categories = new Set(tests.map((t) => t.category || "unknown"));
|
|
748
|
+
return Array.from(categories).map((cat) => {
|
|
749
|
+
const config = testCategoryLabels[cat] || testCategoryLabels.unknown;
|
|
750
|
+
return (
|
|
751
|
+
<Badge
|
|
752
|
+
key={cat}
|
|
753
|
+
variant="outline"
|
|
754
|
+
className="text-xs"
|
|
755
|
+
>
|
|
756
|
+
<span className={`mr-1 h-1.5 w-1.5 rounded-full ${config.color}`} />
|
|
757
|
+
{config.ja}
|
|
758
|
+
</Badge>
|
|
759
|
+
);
|
|
760
|
+
});
|
|
761
|
+
})()}
|
|
762
|
+
</div>
|
|
763
|
+
</div>
|
|
764
|
+
))}
|
|
765
|
+
</div>
|
|
766
|
+
</CardContent>
|
|
767
|
+
</Card>
|
|
768
|
+
</TabsContent>
|
|
769
|
+
|
|
770
|
+
{/* Coverage Gaps Tab */}
|
|
771
|
+
<TabsContent value="gaps" className="mt-4">
|
|
772
|
+
{coverageGaps.length > 0 ? (
|
|
773
|
+
<Card className="border-red-500/30">
|
|
774
|
+
<CardHeader className="pb-4">
|
|
775
|
+
<CardDescription>
|
|
776
|
+
テストが存在しない機能 ({coverageGaps.length}件)
|
|
777
|
+
</CardDescription>
|
|
778
|
+
</CardHeader>
|
|
779
|
+
<CardContent>
|
|
780
|
+
<div className="space-y-6">
|
|
781
|
+
{Object.entries(gapsByType).map(([type, gaps]) => {
|
|
782
|
+
const config = itemTypeConfig[type];
|
|
783
|
+
const Icon = config?.icon || Zap;
|
|
784
|
+
return (
|
|
785
|
+
<div key={type} className="space-y-2">
|
|
786
|
+
<div className="flex items-center gap-2 text-sm font-medium">
|
|
787
|
+
<Icon className="h-4 w-4 text-muted-foreground" />
|
|
788
|
+
<span>{config?.labelJa || type}</span>
|
|
789
|
+
<Badge variant="outline" className="text-xs">{gaps.length}</Badge>
|
|
790
|
+
</div>
|
|
791
|
+
<div className="grid gap-2 md:grid-cols-2 lg:grid-cols-3">
|
|
792
|
+
{gaps.map((gap, idx) => (
|
|
793
|
+
<Link
|
|
794
|
+
key={idx}
|
|
795
|
+
href={`/apps/${appId}/${type}/${encodeURIComponent(gap.module)}/${encodeURIComponent(gap.name)}#tests`}
|
|
796
|
+
className="flex items-center gap-2 rounded-lg border p-2 text-sm hover:bg-muted/50 transition-colors"
|
|
797
|
+
>
|
|
798
|
+
<XCircle className="h-4 w-4 text-red-400 flex-shrink-0" />
|
|
799
|
+
<div className="min-w-0">
|
|
800
|
+
<p className="font-medium truncate">{gap.name}</p>
|
|
801
|
+
<p className="text-xs text-muted-foreground truncate">{gap.module}</p>
|
|
802
|
+
</div>
|
|
803
|
+
</Link>
|
|
804
|
+
))}
|
|
805
|
+
</div>
|
|
806
|
+
</div>
|
|
807
|
+
);
|
|
808
|
+
})}
|
|
809
|
+
</div>
|
|
810
|
+
</CardContent>
|
|
811
|
+
</Card>
|
|
812
|
+
) : (
|
|
813
|
+
<Card className="border-green-500/30">
|
|
814
|
+
<CardContent className="py-8 text-center">
|
|
815
|
+
<CheckCircle2 className="h-8 w-8 text-green-500 mx-auto mb-2" />
|
|
816
|
+
<p className="text-muted-foreground">カバレッジギャップはありません</p>
|
|
817
|
+
</CardContent>
|
|
818
|
+
</Card>
|
|
819
|
+
)}
|
|
820
|
+
</TabsContent>
|
|
821
|
+
</TabsWithHash>
|
|
822
|
+
|
|
823
|
+
{/* Back to all tests link */}
|
|
824
|
+
<div className="flex justify-center">
|
|
825
|
+
<Link
|
|
826
|
+
href="/test-cases"
|
|
827
|
+
className="flex items-center gap-2 text-sm text-muted-foreground hover:text-primary transition-colors"
|
|
828
|
+
>
|
|
829
|
+
<TrendingUp className="h-4 w-4" />
|
|
830
|
+
全アプリのテストダッシュボードを見る
|
|
831
|
+
</Link>
|
|
832
|
+
</div>
|
|
833
|
+
|
|
834
|
+
{/* Generated timestamp */}
|
|
835
|
+
<footer className="text-center text-sm text-muted-foreground">
|
|
836
|
+
<p>Generated at {new Date(data.generatedAt).toLocaleString()}</p>
|
|
837
|
+
</footer>
|
|
838
|
+
</div>
|
|
839
|
+
);
|
|
840
|
+
}
|