@agents-inc/cli 0.32.1
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 +462 -0
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/config/skills-matrix.yaml +926 -0
- package/config/stacks.yaml +2186 -0
- package/dist/chunk-3ZOIOVKT.js +365 -0
- package/dist/chunk-3ZOIOVKT.js.map +1 -0
- package/dist/chunk-4RAY5AOI.js +78 -0
- package/dist/chunk-4RAY5AOI.js.map +1 -0
- package/dist/chunk-5PIKNCZX.js +234 -0
- package/dist/chunk-5PIKNCZX.js.map +1 -0
- package/dist/chunk-66UDJBF6.js +96 -0
- package/dist/chunk-66UDJBF6.js.map +1 -0
- package/dist/chunk-7SOPVGDV.js +24 -0
- package/dist/chunk-7SOPVGDV.js.map +1 -0
- package/dist/chunk-A27LOC4Z.js +95 -0
- package/dist/chunk-A27LOC4Z.js.map +1 -0
- package/dist/chunk-B2UBHA66.js +301 -0
- package/dist/chunk-B2UBHA66.js.map +1 -0
- package/dist/chunk-BZN2Z5P7.js +882 -0
- package/dist/chunk-BZN2Z5P7.js.map +1 -0
- package/dist/chunk-BZQBJP34.js +186 -0
- package/dist/chunk-BZQBJP34.js.map +1 -0
- package/dist/chunk-DC5AK3LW.js +105 -0
- package/dist/chunk-DC5AK3LW.js.map +1 -0
- package/dist/chunk-DHET7RCE.js +50 -0
- package/dist/chunk-DHET7RCE.js.map +1 -0
- package/dist/chunk-EMJ2ZKS7.js +346 -0
- package/dist/chunk-EMJ2ZKS7.js.map +1 -0
- package/dist/chunk-FJQRVFMB.js +48 -0
- package/dist/chunk-FJQRVFMB.js.map +1 -0
- package/dist/chunk-FZGYSLJL.js +85 -0
- package/dist/chunk-FZGYSLJL.js.map +1 -0
- package/dist/chunk-H566H3MQ.js +87 -0
- package/dist/chunk-H566H3MQ.js.map +1 -0
- package/dist/chunk-IYG2LAIM.js +90 -0
- package/dist/chunk-IYG2LAIM.js.map +1 -0
- package/dist/chunk-IZZ4IIEG.js +29 -0
- package/dist/chunk-IZZ4IIEG.js.map +1 -0
- package/dist/chunk-JMVWYAHT.js +63 -0
- package/dist/chunk-JMVWYAHT.js.map +1 -0
- package/dist/chunk-LAPCUV4D.js +191 -0
- package/dist/chunk-LAPCUV4D.js.map +1 -0
- package/dist/chunk-LGUI3PMO.js +109 -0
- package/dist/chunk-LGUI3PMO.js.map +1 -0
- package/dist/chunk-MM7NK5N2.js +4542 -0
- package/dist/chunk-MM7NK5N2.js.map +1 -0
- package/dist/chunk-N6S7ZRIL.js +31 -0
- package/dist/chunk-N6S7ZRIL.js.map +1 -0
- package/dist/chunk-O4D67NN7.js +24 -0
- package/dist/chunk-O4D67NN7.js.map +1 -0
- package/dist/chunk-ODUOU55D.js +56 -0
- package/dist/chunk-ODUOU55D.js.map +1 -0
- package/dist/chunk-OGJIZ6QH.js +497 -0
- package/dist/chunk-OGJIZ6QH.js.map +1 -0
- package/dist/chunk-OMV7TLWD.js +340 -0
- package/dist/chunk-OMV7TLWD.js.map +1 -0
- package/dist/chunk-PBEHPQLK.js +146 -0
- package/dist/chunk-PBEHPQLK.js.map +1 -0
- package/dist/chunk-QPTOIZAT.js +32 -0
- package/dist/chunk-QPTOIZAT.js.map +1 -0
- package/dist/chunk-R3XFQKPG.js +111 -0
- package/dist/chunk-R3XFQKPG.js.map +1 -0
- package/dist/chunk-R74PZWQS.js +69 -0
- package/dist/chunk-R74PZWQS.js.map +1 -0
- package/dist/chunk-SO22IQPY.js +45 -0
- package/dist/chunk-SO22IQPY.js.map +1 -0
- package/dist/chunk-T4EXUIBY.js +19 -0
- package/dist/chunk-T4EXUIBY.js.map +1 -0
- package/dist/chunk-U3IGFMCY.js +31 -0
- package/dist/chunk-U3IGFMCY.js.map +1 -0
- package/dist/chunk-UICL22RT.js +318 -0
- package/dist/chunk-UICL22RT.js.map +1 -0
- package/dist/chunk-UX2H2K2G.js +183 -0
- package/dist/chunk-UX2H2K2G.js.map +1 -0
- package/dist/chunk-W2ZSCZ2U.js +93 -0
- package/dist/chunk-W2ZSCZ2U.js.map +1 -0
- package/dist/chunk-WEUVWHMA.js +189 -0
- package/dist/chunk-WEUVWHMA.js.map +1 -0
- package/dist/chunk-XY3XDVMI.js +15599 -0
- package/dist/chunk-XY3XDVMI.js.map +1 -0
- package/dist/chunk-YND42IXK.js +233 -0
- package/dist/chunk-YND42IXK.js.map +1 -0
- package/dist/chunk-YZTWZVGX.js +41 -0
- package/dist/chunk-YZTWZVGX.js.map +1 -0
- package/dist/chunk-Z4TWOP3H.js +81 -0
- package/dist/chunk-Z4TWOP3H.js.map +1 -0
- package/dist/cli/defaults/agent-mappings.yaml +271 -0
- package/dist/commands/build/marketplace.js +252 -0
- package/dist/commands/build/marketplace.js.map +1 -0
- package/dist/commands/build/plugins.js +114 -0
- package/dist/commands/build/plugins.js.map +1 -0
- package/dist/commands/build/stack.js +153 -0
- package/dist/commands/build/stack.js.map +1 -0
- package/dist/commands/compile.js +354 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/config/get.js +61 -0
- package/dist/commands/config/get.js.map +1 -0
- package/dist/commands/config/index.js +23 -0
- package/dist/commands/config/index.js.map +1 -0
- package/dist/commands/config/path.js +34 -0
- package/dist/commands/config/path.js.map +1 -0
- package/dist/commands/config/set-project.js +61 -0
- package/dist/commands/config/set-project.js.map +1 -0
- package/dist/commands/config/show.js +14 -0
- package/dist/commands/config/show.js.map +1 -0
- package/dist/commands/config/unset-project.js +57 -0
- package/dist/commands/config/unset-project.js.map +1 -0
- package/dist/commands/diff.js +742 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.js +370 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/edit.js +301 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/eject.js +262 -0
- package/dist/commands/eject.js.map +1 -0
- package/dist/commands/import/skill.js +361 -0
- package/dist/commands/import/skill.js.map +1 -0
- package/dist/commands/info.js +217 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/init.js +443 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.js +49 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/new/agent.js +224 -0
- package/dist/commands/new/agent.js.map +1 -0
- package/dist/commands/new/skill.js +199 -0
- package/dist/commands/new/skill.js.map +1 -0
- package/dist/commands/outdated.js +176 -0
- package/dist/commands/outdated.js.map +1 -0
- package/dist/commands/search.js +288 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/uninstall.js +302 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.js +304 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.js +389 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/version/bump.js +79 -0
- package/dist/commands/version/bump.js.map +1 -0
- package/dist/commands/version/index.js +54 -0
- package/dist/commands/version/index.js.map +1 -0
- package/dist/commands/version/set.js +86 -0
- package/dist/commands/version/set.js.map +1 -0
- package/dist/commands/version/show.js +54 -0
- package/dist/commands/version/show.js.map +1 -0
- package/dist/components/common/confirm.js +9 -0
- package/dist/components/common/confirm.js.map +1 -0
- package/dist/components/common/confirm.test.js +203 -0
- package/dist/components/common/confirm.test.js.map +1 -0
- package/dist/components/common/message.js +20 -0
- package/dist/components/common/message.js.map +1 -0
- package/dist/components/common/spinner.js +14 -0
- package/dist/components/common/spinner.js.map +1 -0
- package/dist/components/skill-search/skill-search.js +12 -0
- package/dist/components/skill-search/skill-search.js.map +1 -0
- package/dist/components/wizard/category-grid.js +11 -0
- package/dist/components/wizard/category-grid.js.map +1 -0
- package/dist/components/wizard/category-grid.test.js +997 -0
- package/dist/components/wizard/category-grid.test.js.map +1 -0
- package/dist/components/wizard/domain-selection.js +14 -0
- package/dist/components/wizard/domain-selection.js.map +1 -0
- package/dist/components/wizard/help-modal.js +10 -0
- package/dist/components/wizard/help-modal.js.map +1 -0
- package/dist/components/wizard/menu-item.js +10 -0
- package/dist/components/wizard/menu-item.js.map +1 -0
- package/dist/components/wizard/search-modal.js +11 -0
- package/dist/components/wizard/search-modal.js.map +1 -0
- package/dist/components/wizard/search-modal.test.js +218 -0
- package/dist/components/wizard/search-modal.test.js.map +1 -0
- package/dist/components/wizard/section-progress.js +10 -0
- package/dist/components/wizard/section-progress.js.map +1 -0
- package/dist/components/wizard/section-progress.test.js +192 -0
- package/dist/components/wizard/section-progress.test.js.map +1 -0
- package/dist/components/wizard/source-grid.js +14 -0
- package/dist/components/wizard/source-grid.js.map +1 -0
- package/dist/components/wizard/source-grid.test.js +504 -0
- package/dist/components/wizard/source-grid.test.js.map +1 -0
- package/dist/components/wizard/stack-selection.js +17 -0
- package/dist/components/wizard/stack-selection.js.map +1 -0
- package/dist/components/wizard/step-build.js +17 -0
- package/dist/components/wizard/step-build.js.map +1 -0
- package/dist/components/wizard/step-build.test.js +600 -0
- package/dist/components/wizard/step-build.test.js.map +1 -0
- package/dist/components/wizard/step-confirm.js +12 -0
- package/dist/components/wizard/step-confirm.js.map +1 -0
- package/dist/components/wizard/step-confirm.test.js +366 -0
- package/dist/components/wizard/step-confirm.test.js.map +1 -0
- package/dist/components/wizard/step-refine.js +10 -0
- package/dist/components/wizard/step-refine.js.map +1 -0
- package/dist/components/wizard/step-refine.test.js +237 -0
- package/dist/components/wizard/step-refine.test.js.map +1 -0
- package/dist/components/wizard/step-settings.js +17 -0
- package/dist/components/wizard/step-settings.js.map +1 -0
- package/dist/components/wizard/step-settings.test.js +243 -0
- package/dist/components/wizard/step-settings.test.js.map +1 -0
- package/dist/components/wizard/step-sources.js +20 -0
- package/dist/components/wizard/step-sources.js.map +1 -0
- package/dist/components/wizard/step-sources.test.js +294 -0
- package/dist/components/wizard/step-sources.test.js.map +1 -0
- package/dist/components/wizard/step-stack.js +19 -0
- package/dist/components/wizard/step-stack.js.map +1 -0
- package/dist/components/wizard/step-stack.test.js +357 -0
- package/dist/components/wizard/step-stack.test.js.map +1 -0
- package/dist/components/wizard/view-title.js +10 -0
- package/dist/components/wizard/view-title.js.map +1 -0
- package/dist/components/wizard/wizard-layout.js +16 -0
- package/dist/components/wizard/wizard-layout.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.js +14 -0
- package/dist/components/wizard/wizard-tabs.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.test.js +294 -0
- package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
- package/dist/components/wizard/wizard.js +35 -0
- package/dist/components/wizard/wizard.js.map +1 -0
- package/dist/config/skills-matrix.yaml +926 -0
- package/dist/config/stacks.yaml +2186 -0
- package/dist/hooks/init.js +40 -0
- package/dist/hooks/init.js.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/magic-string.es-RGXYGAW3.js +1316 -0
- package/dist/magic-string.es-RGXYGAW3.js.map +1 -0
- package/dist/source-manager-SBPPLOQQ.js +16 -0
- package/dist/source-manager-SBPPLOQQ.js.map +1 -0
- package/dist/src/agents/_templates/agent.liquid +140 -0
- package/dist/src/agents/developer/api-developer/agent.yaml +12 -0
- package/dist/src/agents/developer/api-developer/critical-reminders.md +23 -0
- package/dist/src/agents/developer/api-developer/critical-requirements.md +11 -0
- package/dist/src/agents/developer/api-developer/examples.md +72 -0
- package/dist/src/agents/developer/api-developer/intro.md +22 -0
- package/dist/src/agents/developer/api-developer/output-format.md +359 -0
- package/dist/src/agents/developer/api-developer/workflow.md +471 -0
- package/dist/src/agents/developer/cli-developer/agent.yaml +12 -0
- package/dist/src/agents/developer/cli-developer/critical-reminders.md +28 -0
- package/dist/src/agents/developer/cli-developer/critical-requirements.md +15 -0
- package/dist/src/agents/developer/cli-developer/examples.md +68 -0
- package/dist/src/agents/developer/cli-developer/intro.md +23 -0
- package/dist/src/agents/developer/cli-developer/output-format.md +216 -0
- package/dist/src/agents/developer/cli-developer/workflow.md +509 -0
- package/dist/src/agents/developer/web-architecture/agent.yaml +12 -0
- package/dist/src/agents/developer/web-architecture/critical-reminders.md +27 -0
- package/dist/src/agents/developer/web-architecture/critical-requirements.md +35 -0
- package/dist/src/agents/developer/web-architecture/examples.md +187 -0
- package/dist/src/agents/developer/web-architecture/intro.md +35 -0
- package/dist/src/agents/developer/web-architecture/output-format.md +261 -0
- package/dist/src/agents/developer/web-architecture/workflow.md +599 -0
- package/dist/src/agents/developer/web-developer/agent.yaml +12 -0
- package/dist/src/agents/developer/web-developer/critical-reminders.md +17 -0
- package/dist/src/agents/developer/web-developer/critical-requirements.md +15 -0
- package/dist/src/agents/developer/web-developer/examples.md +109 -0
- package/dist/src/agents/developer/web-developer/intro.md +5 -0
- package/dist/src/agents/developer/web-developer/output-format.md +213 -0
- package/dist/src/agents/developer/web-developer/workflow.md +459 -0
- package/dist/src/agents/meta/agent-summoner/agent.yaml +12 -0
- package/dist/src/agents/meta/agent-summoner/critical-reminders.md +31 -0
- package/dist/src/agents/meta/agent-summoner/critical-requirements.md +27 -0
- package/dist/src/agents/meta/agent-summoner/examples.md +176 -0
- package/dist/src/agents/meta/agent-summoner/intro.md +9 -0
- package/dist/src/agents/meta/agent-summoner/output-format.md +115 -0
- package/dist/src/agents/meta/agent-summoner/workflow.md +1540 -0
- package/dist/src/agents/meta/documentor/agent.yaml +11 -0
- package/dist/src/agents/meta/documentor/critical-reminders.md +23 -0
- package/dist/src/agents/meta/documentor/critical-requirements.md +13 -0
- package/dist/src/agents/meta/documentor/examples.md +147 -0
- package/dist/src/agents/meta/documentor/intro.md +11 -0
- package/dist/src/agents/meta/documentor/output-format.md +237 -0
- package/dist/src/agents/meta/documentor/workflow.md +1271 -0
- package/dist/src/agents/meta/skill-summoner/agent.yaml +13 -0
- package/dist/src/agents/meta/skill-summoner/critical-reminders.md +73 -0
- package/dist/src/agents/meta/skill-summoner/critical-requirements.md +62 -0
- package/dist/src/agents/meta/skill-summoner/examples.md +116 -0
- package/dist/src/agents/meta/skill-summoner/intro.md +5 -0
- package/dist/src/agents/meta/skill-summoner/output-format.md +279 -0
- package/dist/src/agents/meta/skill-summoner/workflow.md +1485 -0
- package/dist/src/agents/migration/cli-migrator/agent.yaml +12 -0
- package/dist/src/agents/migration/cli-migrator/anti-patterns.md +158 -0
- package/dist/src/agents/migration/cli-migrator/conversion-mappings.md +63 -0
- package/dist/src/agents/migration/cli-migrator/critical-reminders.md +17 -0
- package/dist/src/agents/migration/cli-migrator/critical-requirements.md +13 -0
- package/dist/src/agents/migration/cli-migrator/intro.md +15 -0
- package/dist/src/agents/migration/cli-migrator/output-format.md +164 -0
- package/dist/src/agents/migration/cli-migrator/workflow.md +230 -0
- package/dist/src/agents/pattern/pattern-scout/agent.yaml +10 -0
- package/dist/src/agents/pattern/pattern-scout/critical-reminders.md +58 -0
- package/dist/src/agents/pattern/pattern-scout/critical-requirements.md +17 -0
- package/dist/src/agents/pattern/pattern-scout/examples.md +93 -0
- package/dist/src/agents/pattern/pattern-scout/intro.md +3 -0
- package/dist/src/agents/pattern/pattern-scout/output-format.md +196 -0
- package/dist/src/agents/pattern/pattern-scout/workflow.md +1901 -0
- package/dist/src/agents/pattern/web-pattern-critique/agent.yaml +12 -0
- package/dist/src/agents/pattern/web-pattern-critique/critical-reminders.md +13 -0
- package/dist/src/agents/pattern/web-pattern-critique/critical-requirements.md +11 -0
- package/dist/src/agents/pattern/web-pattern-critique/examples.md +56 -0
- package/dist/src/agents/pattern/web-pattern-critique/intro.md +5 -0
- package/dist/src/agents/pattern/web-pattern-critique/output-format.md +257 -0
- package/dist/src/agents/pattern/web-pattern-critique/workflow.md +674 -0
- package/dist/src/agents/planning/web-pm/agent.yaml +12 -0
- package/dist/src/agents/planning/web-pm/critical-reminders.md +21 -0
- package/dist/src/agents/planning/web-pm/critical-requirements.md +17 -0
- package/dist/src/agents/planning/web-pm/examples.md +85 -0
- package/dist/src/agents/planning/web-pm/intro.md +3 -0
- package/dist/src/agents/planning/web-pm/output-format.md +228 -0
- package/dist/src/agents/planning/web-pm/workflow.md +393 -0
- package/dist/src/agents/researcher/api-researcher/agent.yaml +10 -0
- package/dist/src/agents/researcher/api-researcher/critical-reminders.md +27 -0
- package/dist/src/agents/researcher/api-researcher/critical-requirements.md +13 -0
- package/dist/src/agents/researcher/api-researcher/examples.md +116 -0
- package/dist/src/agents/researcher/api-researcher/intro.md +32 -0
- package/dist/src/agents/researcher/api-researcher/output-format.md +135 -0
- package/dist/src/agents/researcher/api-researcher/workflow.md +261 -0
- package/dist/src/agents/researcher/web-researcher/agent.yaml +10 -0
- package/dist/src/agents/researcher/web-researcher/critical-reminders.md +23 -0
- package/dist/src/agents/researcher/web-researcher/critical-requirements.md +11 -0
- package/dist/src/agents/researcher/web-researcher/examples.md +126 -0
- package/dist/src/agents/researcher/web-researcher/intro.md +31 -0
- package/dist/src/agents/researcher/web-researcher/output-format.md +112 -0
- package/dist/src/agents/researcher/web-researcher/workflow.md +322 -0
- package/dist/src/agents/reviewer/api-reviewer/agent.yaml +12 -0
- package/dist/src/agents/reviewer/api-reviewer/critical-reminders.md +16 -0
- package/dist/src/agents/reviewer/api-reviewer/critical-requirements.md +13 -0
- package/dist/src/agents/reviewer/api-reviewer/examples.md +54 -0
- package/dist/src/agents/reviewer/api-reviewer/intro.md +22 -0
- package/dist/src/agents/reviewer/api-reviewer/output-format.md +288 -0
- package/dist/src/agents/reviewer/api-reviewer/workflow.md +369 -0
- package/dist/src/agents/reviewer/cli-reviewer/agent.yaml +12 -0
- package/dist/src/agents/reviewer/cli-reviewer/critical-reminders.md +17 -0
- package/dist/src/agents/reviewer/cli-reviewer/critical-requirements.md +13 -0
- package/dist/src/agents/reviewer/cli-reviewer/examples.md +83 -0
- package/dist/src/agents/reviewer/cli-reviewer/intro.md +21 -0
- package/dist/src/agents/reviewer/cli-reviewer/output-format.md +330 -0
- package/dist/src/agents/reviewer/cli-reviewer/workflow.md +294 -0
- package/dist/src/agents/reviewer/web-reviewer/agent.yaml +12 -0
- package/dist/src/agents/reviewer/web-reviewer/critical-reminders.md +17 -0
- package/dist/src/agents/reviewer/web-reviewer/critical-requirements.md +11 -0
- package/dist/src/agents/reviewer/web-reviewer/examples.md +79 -0
- package/dist/src/agents/reviewer/web-reviewer/intro.md +20 -0
- package/dist/src/agents/reviewer/web-reviewer/output-format.md +253 -0
- package/dist/src/agents/reviewer/web-reviewer/workflow.md +228 -0
- package/dist/src/agents/tester/cli-tester/agent.yaml +12 -0
- package/dist/src/agents/tester/cli-tester/critical-reminders.md +19 -0
- package/dist/src/agents/tester/cli-tester/critical-requirements.md +17 -0
- package/dist/src/agents/tester/cli-tester/examples.md +80 -0
- package/dist/src/agents/tester/cli-tester/intro.md +19 -0
- package/dist/src/agents/tester/cli-tester/output-format.md +232 -0
- package/dist/src/agents/tester/cli-tester/workflow.md +304 -0
- package/dist/src/agents/tester/web-tester/agent.yaml +12 -0
- package/dist/src/agents/tester/web-tester/critical-reminders.md +15 -0
- package/dist/src/agents/tester/web-tester/critical-requirements.md +11 -0
- package/dist/src/agents/tester/web-tester/examples.md +68 -0
- package/dist/src/agents/tester/web-tester/intro.md +18 -0
- package/dist/src/agents/tester/web-tester/output-format.md +252 -0
- package/dist/src/agents/tester/web-tester/workflow.md +507 -0
- package/dist/stores/wizard-store.js +13 -0
- package/dist/stores/wizard-store.js.map +1 -0
- package/dist/stores/wizard-store.test.js +689 -0
- package/dist/stores/wizard-store.test.js.map +1 -0
- package/package.json +134 -0
- package/src/agents/_templates/agent.liquid +140 -0
- package/src/agents/developer/api-developer/agent.yaml +12 -0
- package/src/agents/developer/api-developer/critical-reminders.md +23 -0
- package/src/agents/developer/api-developer/critical-requirements.md +11 -0
- package/src/agents/developer/api-developer/examples.md +72 -0
- package/src/agents/developer/api-developer/intro.md +22 -0
- package/src/agents/developer/api-developer/output-format.md +359 -0
- package/src/agents/developer/api-developer/workflow.md +471 -0
- package/src/agents/developer/cli-developer/agent.yaml +12 -0
- package/src/agents/developer/cli-developer/critical-reminders.md +28 -0
- package/src/agents/developer/cli-developer/critical-requirements.md +15 -0
- package/src/agents/developer/cli-developer/examples.md +68 -0
- package/src/agents/developer/cli-developer/intro.md +23 -0
- package/src/agents/developer/cli-developer/output-format.md +216 -0
- package/src/agents/developer/cli-developer/workflow.md +509 -0
- package/src/agents/developer/web-architecture/agent.yaml +12 -0
- package/src/agents/developer/web-architecture/critical-reminders.md +27 -0
- package/src/agents/developer/web-architecture/critical-requirements.md +35 -0
- package/src/agents/developer/web-architecture/examples.md +187 -0
- package/src/agents/developer/web-architecture/intro.md +35 -0
- package/src/agents/developer/web-architecture/output-format.md +261 -0
- package/src/agents/developer/web-architecture/workflow.md +599 -0
- package/src/agents/developer/web-developer/agent.yaml +12 -0
- package/src/agents/developer/web-developer/critical-reminders.md +17 -0
- package/src/agents/developer/web-developer/critical-requirements.md +15 -0
- package/src/agents/developer/web-developer/examples.md +109 -0
- package/src/agents/developer/web-developer/intro.md +5 -0
- package/src/agents/developer/web-developer/output-format.md +213 -0
- package/src/agents/developer/web-developer/workflow.md +459 -0
- package/src/agents/meta/agent-summoner/agent.yaml +12 -0
- package/src/agents/meta/agent-summoner/critical-reminders.md +31 -0
- package/src/agents/meta/agent-summoner/critical-requirements.md +27 -0
- package/src/agents/meta/agent-summoner/examples.md +176 -0
- package/src/agents/meta/agent-summoner/intro.md +9 -0
- package/src/agents/meta/agent-summoner/output-format.md +115 -0
- package/src/agents/meta/agent-summoner/workflow.md +1540 -0
- package/src/agents/meta/documentor/agent.yaml +11 -0
- package/src/agents/meta/documentor/critical-reminders.md +23 -0
- package/src/agents/meta/documentor/critical-requirements.md +13 -0
- package/src/agents/meta/documentor/examples.md +147 -0
- package/src/agents/meta/documentor/intro.md +11 -0
- package/src/agents/meta/documentor/output-format.md +237 -0
- package/src/agents/meta/documentor/workflow.md +1271 -0
- package/src/agents/meta/skill-summoner/agent.yaml +13 -0
- package/src/agents/meta/skill-summoner/critical-reminders.md +73 -0
- package/src/agents/meta/skill-summoner/critical-requirements.md +62 -0
- package/src/agents/meta/skill-summoner/examples.md +116 -0
- package/src/agents/meta/skill-summoner/intro.md +5 -0
- package/src/agents/meta/skill-summoner/output-format.md +279 -0
- package/src/agents/meta/skill-summoner/workflow.md +1485 -0
- package/src/agents/migration/cli-migrator/agent.yaml +12 -0
- package/src/agents/migration/cli-migrator/anti-patterns.md +158 -0
- package/src/agents/migration/cli-migrator/conversion-mappings.md +63 -0
- package/src/agents/migration/cli-migrator/critical-reminders.md +17 -0
- package/src/agents/migration/cli-migrator/critical-requirements.md +13 -0
- package/src/agents/migration/cli-migrator/intro.md +15 -0
- package/src/agents/migration/cli-migrator/output-format.md +164 -0
- package/src/agents/migration/cli-migrator/workflow.md +230 -0
- package/src/agents/pattern/pattern-scout/agent.yaml +10 -0
- package/src/agents/pattern/pattern-scout/critical-reminders.md +58 -0
- package/src/agents/pattern/pattern-scout/critical-requirements.md +17 -0
- package/src/agents/pattern/pattern-scout/examples.md +93 -0
- package/src/agents/pattern/pattern-scout/intro.md +3 -0
- package/src/agents/pattern/pattern-scout/output-format.md +196 -0
- package/src/agents/pattern/pattern-scout/workflow.md +1901 -0
- package/src/agents/pattern/web-pattern-critique/agent.yaml +12 -0
- package/src/agents/pattern/web-pattern-critique/critical-reminders.md +13 -0
- package/src/agents/pattern/web-pattern-critique/critical-requirements.md +11 -0
- package/src/agents/pattern/web-pattern-critique/examples.md +56 -0
- package/src/agents/pattern/web-pattern-critique/intro.md +5 -0
- package/src/agents/pattern/web-pattern-critique/output-format.md +257 -0
- package/src/agents/pattern/web-pattern-critique/workflow.md +674 -0
- package/src/agents/planning/web-pm/agent.yaml +12 -0
- package/src/agents/planning/web-pm/critical-reminders.md +21 -0
- package/src/agents/planning/web-pm/critical-requirements.md +17 -0
- package/src/agents/planning/web-pm/examples.md +85 -0
- package/src/agents/planning/web-pm/intro.md +3 -0
- package/src/agents/planning/web-pm/output-format.md +228 -0
- package/src/agents/planning/web-pm/workflow.md +393 -0
- package/src/agents/researcher/api-researcher/agent.yaml +10 -0
- package/src/agents/researcher/api-researcher/critical-reminders.md +27 -0
- package/src/agents/researcher/api-researcher/critical-requirements.md +13 -0
- package/src/agents/researcher/api-researcher/examples.md +116 -0
- package/src/agents/researcher/api-researcher/intro.md +32 -0
- package/src/agents/researcher/api-researcher/output-format.md +135 -0
- package/src/agents/researcher/api-researcher/workflow.md +261 -0
- package/src/agents/researcher/web-researcher/agent.yaml +10 -0
- package/src/agents/researcher/web-researcher/critical-reminders.md +23 -0
- package/src/agents/researcher/web-researcher/critical-requirements.md +11 -0
- package/src/agents/researcher/web-researcher/examples.md +126 -0
- package/src/agents/researcher/web-researcher/intro.md +31 -0
- package/src/agents/researcher/web-researcher/output-format.md +112 -0
- package/src/agents/researcher/web-researcher/workflow.md +322 -0
- package/src/agents/reviewer/api-reviewer/agent.yaml +12 -0
- package/src/agents/reviewer/api-reviewer/critical-reminders.md +16 -0
- package/src/agents/reviewer/api-reviewer/critical-requirements.md +13 -0
- package/src/agents/reviewer/api-reviewer/examples.md +54 -0
- package/src/agents/reviewer/api-reviewer/intro.md +22 -0
- package/src/agents/reviewer/api-reviewer/output-format.md +288 -0
- package/src/agents/reviewer/api-reviewer/workflow.md +369 -0
- package/src/agents/reviewer/cli-reviewer/agent.yaml +12 -0
- package/src/agents/reviewer/cli-reviewer/critical-reminders.md +17 -0
- package/src/agents/reviewer/cli-reviewer/critical-requirements.md +13 -0
- package/src/agents/reviewer/cli-reviewer/examples.md +83 -0
- package/src/agents/reviewer/cli-reviewer/intro.md +21 -0
- package/src/agents/reviewer/cli-reviewer/output-format.md +330 -0
- package/src/agents/reviewer/cli-reviewer/workflow.md +294 -0
- package/src/agents/reviewer/web-reviewer/agent.yaml +12 -0
- package/src/agents/reviewer/web-reviewer/critical-reminders.md +17 -0
- package/src/agents/reviewer/web-reviewer/critical-requirements.md +11 -0
- package/src/agents/reviewer/web-reviewer/examples.md +79 -0
- package/src/agents/reviewer/web-reviewer/intro.md +20 -0
- package/src/agents/reviewer/web-reviewer/output-format.md +253 -0
- package/src/agents/reviewer/web-reviewer/workflow.md +228 -0
- package/src/agents/tester/cli-tester/agent.yaml +12 -0
- package/src/agents/tester/cli-tester/critical-reminders.md +19 -0
- package/src/agents/tester/cli-tester/critical-requirements.md +17 -0
- package/src/agents/tester/cli-tester/examples.md +80 -0
- package/src/agents/tester/cli-tester/intro.md +19 -0
- package/src/agents/tester/cli-tester/output-format.md +232 -0
- package/src/agents/tester/cli-tester/workflow.md +304 -0
- package/src/agents/tester/web-tester/agent.yaml +12 -0
- package/src/agents/tester/web-tester/critical-reminders.md +15 -0
- package/src/agents/tester/web-tester/critical-requirements.md +11 -0
- package/src/agents/tester/web-tester/examples.md +68 -0
- package/src/agents/tester/web-tester/intro.md +18 -0
- package/src/agents/tester/web-tester/output-format.md +252 -0
- package/src/agents/tester/web-tester/workflow.md +507 -0
- package/src/schemas/agent-frontmatter.schema.json +84 -0
- package/src/schemas/agent.schema.json +93 -0
- package/src/schemas/hooks.schema.json +47 -0
- package/src/schemas/marketplace.schema.json +119 -0
- package/src/schemas/metadata.schema.json +113 -0
- package/src/schemas/plugin.schema.json +130 -0
- package/src/schemas/project-config.schema.json +125 -0
- package/src/schemas/project-source-config.schema.json +81 -0
- package/src/schemas/skill-frontmatter.schema.json +42 -0
- package/src/schemas/skills-matrix.schema.json +467 -0
- package/src/schemas/stack.schema.json +191 -0
- package/src/schemas/stacks.schema.json +111 -0
|
@@ -0,0 +1,997 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ARROW_DOWN,
|
|
4
|
+
ARROW_LEFT,
|
|
5
|
+
ARROW_RIGHT,
|
|
6
|
+
ARROW_UP,
|
|
7
|
+
INPUT_DELAY_MS,
|
|
8
|
+
RENDER_DELAY_MS,
|
|
9
|
+
TAB,
|
|
10
|
+
delay
|
|
11
|
+
} from "../../chunk-YZTWZVGX.js";
|
|
12
|
+
import {
|
|
13
|
+
render
|
|
14
|
+
} from "../../chunk-66UDJBF6.js";
|
|
15
|
+
import {
|
|
16
|
+
afterEach,
|
|
17
|
+
describe,
|
|
18
|
+
globalExpect,
|
|
19
|
+
it,
|
|
20
|
+
vi
|
|
21
|
+
} from "../../chunk-XY3XDVMI.js";
|
|
22
|
+
import {
|
|
23
|
+
CategoryGrid
|
|
24
|
+
} from "../../chunk-OGJIZ6QH.js";
|
|
25
|
+
import "../../chunk-DC5AK3LW.js";
|
|
26
|
+
import {
|
|
27
|
+
UI_SYMBOLS
|
|
28
|
+
} from "../../chunk-LAPCUV4D.js";
|
|
29
|
+
import {
|
|
30
|
+
init_esm_shims
|
|
31
|
+
} from "../../chunk-DHET7RCE.js";
|
|
32
|
+
|
|
33
|
+
// src/cli/components/wizard/category-grid.test.tsx
|
|
34
|
+
init_esm_shims();
|
|
35
|
+
import { jsx } from "react/jsx-runtime";
|
|
36
|
+
var createOption = (id, label, overrides = {}) => ({
|
|
37
|
+
id,
|
|
38
|
+
label,
|
|
39
|
+
state: "normal",
|
|
40
|
+
selected: false,
|
|
41
|
+
...overrides
|
|
42
|
+
});
|
|
43
|
+
var createCategory = (id, displayName, options, overrides = {}) => ({
|
|
44
|
+
id,
|
|
45
|
+
displayName,
|
|
46
|
+
required: false,
|
|
47
|
+
exclusive: true,
|
|
48
|
+
options,
|
|
49
|
+
...overrides
|
|
50
|
+
});
|
|
51
|
+
var defaultCategories = [
|
|
52
|
+
createCategory(
|
|
53
|
+
"framework",
|
|
54
|
+
"Framework",
|
|
55
|
+
[
|
|
56
|
+
createOption("web-test-react", "React", {
|
|
57
|
+
state: "recommended",
|
|
58
|
+
stateReason: "Popular choice"
|
|
59
|
+
}),
|
|
60
|
+
createOption("web-test-vue", "Vue"),
|
|
61
|
+
createOption("web-test-angular", "Angular"),
|
|
62
|
+
createOption("web-test-svelte", "Svelte")
|
|
63
|
+
],
|
|
64
|
+
{ required: true }
|
|
65
|
+
),
|
|
66
|
+
createCategory(
|
|
67
|
+
"styling",
|
|
68
|
+
"Styling",
|
|
69
|
+
[
|
|
70
|
+
createOption("web-scss-mod", "SCSS Modules", { selected: true }),
|
|
71
|
+
createOption("web-test-tailwind", "Tailwind", { state: "recommended" }),
|
|
72
|
+
createOption("web-test-styled", "Styled Components"),
|
|
73
|
+
createOption("web-test-vanilla", "Vanilla CSS")
|
|
74
|
+
],
|
|
75
|
+
{ required: true }
|
|
76
|
+
),
|
|
77
|
+
createCategory("client-state", "Client State", [
|
|
78
|
+
createOption("web-test-zustand", "Zustand", { state: "recommended" }),
|
|
79
|
+
createOption("web-test-jotai", "Jotai"),
|
|
80
|
+
createOption("web-test-redux", "Redux", {
|
|
81
|
+
state: "discouraged",
|
|
82
|
+
stateReason: "Complex for most apps"
|
|
83
|
+
}),
|
|
84
|
+
createOption("web-test-mobx", "MobX")
|
|
85
|
+
]),
|
|
86
|
+
createCategory("server-state", "Server State", [
|
|
87
|
+
createOption("web-react-query", "React Query", { selected: true }),
|
|
88
|
+
createOption("web-test-swr", "SWR"),
|
|
89
|
+
createOption("web-test-apollo", "Apollo")
|
|
90
|
+
]),
|
|
91
|
+
createCategory("analytics", "Analytics", [createOption("web-test-posthog", "PostHog")])
|
|
92
|
+
];
|
|
93
|
+
var categoriesWithFramework = [
|
|
94
|
+
createCategory(
|
|
95
|
+
"framework",
|
|
96
|
+
"Framework",
|
|
97
|
+
[
|
|
98
|
+
createOption("web-test-react", "React", {
|
|
99
|
+
state: "recommended",
|
|
100
|
+
stateReason: "Popular choice",
|
|
101
|
+
selected: true
|
|
102
|
+
// Framework selected
|
|
103
|
+
}),
|
|
104
|
+
createOption("web-test-vue", "Vue"),
|
|
105
|
+
createOption("web-test-angular", "Angular"),
|
|
106
|
+
createOption("web-test-svelte", "Svelte")
|
|
107
|
+
],
|
|
108
|
+
{ required: true }
|
|
109
|
+
),
|
|
110
|
+
createCategory(
|
|
111
|
+
"styling",
|
|
112
|
+
"Styling",
|
|
113
|
+
[
|
|
114
|
+
createOption("web-scss-mod", "SCSS Modules"),
|
|
115
|
+
createOption("web-test-tailwind", "Tailwind", { state: "recommended" }),
|
|
116
|
+
createOption("web-test-styled", "Styled Components"),
|
|
117
|
+
createOption("web-test-vanilla", "Vanilla CSS")
|
|
118
|
+
],
|
|
119
|
+
{ required: true }
|
|
120
|
+
),
|
|
121
|
+
createCategory("client-state", "Client State", [
|
|
122
|
+
createOption("web-test-zustand", "Zustand", { state: "recommended" }),
|
|
123
|
+
createOption("web-test-jotai", "Jotai"),
|
|
124
|
+
createOption("web-test-redux", "Redux", { state: "discouraged" }),
|
|
125
|
+
createOption("web-test-mobx", "MobX")
|
|
126
|
+
])
|
|
127
|
+
];
|
|
128
|
+
var defaultProps = {
|
|
129
|
+
categories: defaultCategories,
|
|
130
|
+
defaultFocusedRow: 0,
|
|
131
|
+
defaultFocusedCol: 0,
|
|
132
|
+
showDescriptions: false,
|
|
133
|
+
expertMode: false,
|
|
134
|
+
onToggle: vi.fn(),
|
|
135
|
+
onFocusChange: vi.fn(),
|
|
136
|
+
onToggleDescriptions: vi.fn()
|
|
137
|
+
};
|
|
138
|
+
var renderGrid = (props = {}) => {
|
|
139
|
+
return render(/* @__PURE__ */ jsx(CategoryGrid, { ...defaultProps, ...props }));
|
|
140
|
+
};
|
|
141
|
+
describe("CategoryGrid component", () => {
|
|
142
|
+
let cleanup;
|
|
143
|
+
afterEach(() => {
|
|
144
|
+
cleanup?.();
|
|
145
|
+
cleanup = void 0;
|
|
146
|
+
});
|
|
147
|
+
describe("rendering", () => {
|
|
148
|
+
it("should render all categories as sections", () => {
|
|
149
|
+
const { lastFrame, unmount } = renderGrid();
|
|
150
|
+
cleanup = unmount;
|
|
151
|
+
const output = lastFrame();
|
|
152
|
+
globalExpect(output).toContain("Framework");
|
|
153
|
+
globalExpect(output).toContain("Styling");
|
|
154
|
+
globalExpect(output).toContain("Client State");
|
|
155
|
+
globalExpect(output).toContain("Server State");
|
|
156
|
+
globalExpect(output).toContain("Analytics");
|
|
157
|
+
});
|
|
158
|
+
it("should render all options in each category", () => {
|
|
159
|
+
const { lastFrame, unmount } = renderGrid();
|
|
160
|
+
cleanup = unmount;
|
|
161
|
+
const output = lastFrame();
|
|
162
|
+
globalExpect(output).toContain("React");
|
|
163
|
+
globalExpect(output).toContain("Vue");
|
|
164
|
+
globalExpect(output).toContain("Angular");
|
|
165
|
+
globalExpect(output).toContain("Svelte");
|
|
166
|
+
globalExpect(output).toContain("SCSS Modules");
|
|
167
|
+
globalExpect(output).toContain("Tailwind");
|
|
168
|
+
});
|
|
169
|
+
it("should show required indicator (*) for required categories", () => {
|
|
170
|
+
const { lastFrame, unmount } = renderGrid();
|
|
171
|
+
cleanup = unmount;
|
|
172
|
+
const output = lastFrame();
|
|
173
|
+
globalExpect(output).toContain("*");
|
|
174
|
+
});
|
|
175
|
+
it("should NOT show (optional) for non-required categories", () => {
|
|
176
|
+
const { lastFrame, unmount } = renderGrid();
|
|
177
|
+
cleanup = unmount;
|
|
178
|
+
const output = lastFrame();
|
|
179
|
+
globalExpect(output).not.toContain("(optional)");
|
|
180
|
+
});
|
|
181
|
+
it("should handle empty categories array", () => {
|
|
182
|
+
const { lastFrame, unmount } = renderGrid({ categories: [] });
|
|
183
|
+
cleanup = unmount;
|
|
184
|
+
const output = lastFrame();
|
|
185
|
+
globalExpect(output).toContain("No categories to display");
|
|
186
|
+
});
|
|
187
|
+
it("should render section underlines", () => {
|
|
188
|
+
const { lastFrame, unmount } = renderGrid();
|
|
189
|
+
cleanup = unmount;
|
|
190
|
+
const output = lastFrame();
|
|
191
|
+
globalExpect(output).toContain("\u2500");
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe("visual states", () => {
|
|
195
|
+
it("should show selected options with label text", () => {
|
|
196
|
+
const { lastFrame, unmount } = renderGrid();
|
|
197
|
+
cleanup = unmount;
|
|
198
|
+
const output = lastFrame();
|
|
199
|
+
globalExpect(output).toContain("SCSS Modules");
|
|
200
|
+
globalExpect(output).toContain("React Query");
|
|
201
|
+
});
|
|
202
|
+
it("should show unselected options with label text", () => {
|
|
203
|
+
const { lastFrame, unmount } = renderGrid();
|
|
204
|
+
cleanup = unmount;
|
|
205
|
+
const output = lastFrame();
|
|
206
|
+
globalExpect(output).toContain("Vue");
|
|
207
|
+
globalExpect(output).toContain("Angular");
|
|
208
|
+
});
|
|
209
|
+
it("should NOT show star indicator for recommended options (uses background instead)", () => {
|
|
210
|
+
const { lastFrame, unmount } = renderGrid();
|
|
211
|
+
cleanup = unmount;
|
|
212
|
+
const output = lastFrame();
|
|
213
|
+
globalExpect(output).not.toContain("\u2B50");
|
|
214
|
+
});
|
|
215
|
+
it("should NOT show warning indicator for discouraged options (uses color instead)", () => {
|
|
216
|
+
const { lastFrame, unmount } = renderGrid();
|
|
217
|
+
cleanup = unmount;
|
|
218
|
+
const output = lastFrame();
|
|
219
|
+
globalExpect(output).not.toContain("\u26A0");
|
|
220
|
+
});
|
|
221
|
+
it("should show disabled options with dimmed styling", () => {
|
|
222
|
+
const categories = [
|
|
223
|
+
createCategory("testing", "Test", [
|
|
224
|
+
createOption("web-test-opt1", "Option 1"),
|
|
225
|
+
createOption("web-test-opt2", "Option 2", { state: "disabled" })
|
|
226
|
+
])
|
|
227
|
+
];
|
|
228
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
229
|
+
cleanup = unmount;
|
|
230
|
+
const output = lastFrame();
|
|
231
|
+
globalExpect(output).toContain("Option 2");
|
|
232
|
+
});
|
|
233
|
+
it("should show selected symbol for selected skills", () => {
|
|
234
|
+
const categories = [
|
|
235
|
+
createCategory("forms", "Forms", [
|
|
236
|
+
createOption("web-test-opt1", "Selected Skill", { selected: true })
|
|
237
|
+
])
|
|
238
|
+
];
|
|
239
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
240
|
+
cleanup = unmount;
|
|
241
|
+
const output = lastFrame();
|
|
242
|
+
globalExpect(output).toContain(UI_SYMBOLS.SELECTED);
|
|
243
|
+
globalExpect(output).toContain("Selected Skill");
|
|
244
|
+
});
|
|
245
|
+
it("should show unselected symbol for normal unselected skills", () => {
|
|
246
|
+
const categories = [
|
|
247
|
+
createCategory("forms", "Forms", [
|
|
248
|
+
createOption("web-test-opt1", "Unselected Skill", { state: "normal", selected: false })
|
|
249
|
+
])
|
|
250
|
+
];
|
|
251
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
252
|
+
cleanup = unmount;
|
|
253
|
+
const output = lastFrame();
|
|
254
|
+
globalExpect(output).toContain(UI_SYMBOLS.UNSELECTED);
|
|
255
|
+
globalExpect(output).toContain("Unselected Skill");
|
|
256
|
+
});
|
|
257
|
+
it("should show disabled symbol for disabled skills", () => {
|
|
258
|
+
const categories = [
|
|
259
|
+
createCategory("forms", "Forms", [
|
|
260
|
+
createOption("web-test-opt1", "Disabled Skill", { state: "disabled" })
|
|
261
|
+
])
|
|
262
|
+
];
|
|
263
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
264
|
+
cleanup = unmount;
|
|
265
|
+
const output = lastFrame();
|
|
266
|
+
globalExpect(output).toContain(UI_SYMBOLS.DISABLED);
|
|
267
|
+
globalExpect(output).toContain("Disabled Skill");
|
|
268
|
+
});
|
|
269
|
+
it("should show discouraged symbol for discouraged skills", () => {
|
|
270
|
+
const categories = [
|
|
271
|
+
createCategory("forms", "Forms", [
|
|
272
|
+
createOption("web-test-opt1", "Discouraged Skill", { state: "discouraged" })
|
|
273
|
+
])
|
|
274
|
+
];
|
|
275
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
276
|
+
cleanup = unmount;
|
|
277
|
+
const output = lastFrame();
|
|
278
|
+
globalExpect(output).toContain(UI_SYMBOLS.DISCOURAGED);
|
|
279
|
+
globalExpect(output).toContain("Discouraged Skill");
|
|
280
|
+
});
|
|
281
|
+
it("should differentiate selected vs unselected with different symbols", () => {
|
|
282
|
+
const categories = [
|
|
283
|
+
createCategory("forms", "Forms", [
|
|
284
|
+
createOption("web-test-opt1", "Active", { selected: true }),
|
|
285
|
+
createOption("web-test-opt2", "Inactive", { selected: false })
|
|
286
|
+
])
|
|
287
|
+
];
|
|
288
|
+
const { lastFrame, unmount } = renderGrid({ categories, expertMode: true });
|
|
289
|
+
cleanup = unmount;
|
|
290
|
+
const output = lastFrame();
|
|
291
|
+
globalExpect(output).toContain(UI_SYMBOLS.SELECTED);
|
|
292
|
+
globalExpect(output).toContain(UI_SYMBOLS.UNSELECTED);
|
|
293
|
+
globalExpect(output).toContain("Active");
|
|
294
|
+
globalExpect(output).toContain("Inactive");
|
|
295
|
+
});
|
|
296
|
+
it("should toggle visual state when selection changes", () => {
|
|
297
|
+
const categories1 = [
|
|
298
|
+
createCategory("forms", "Forms", [
|
|
299
|
+
createOption("web-test-opt1", "Toggle Skill", { selected: false })
|
|
300
|
+
])
|
|
301
|
+
];
|
|
302
|
+
const { lastFrame: frame1, unmount: unmount1 } = renderGrid({ categories: categories1 });
|
|
303
|
+
const output1 = frame1();
|
|
304
|
+
unmount1();
|
|
305
|
+
const categories2 = [
|
|
306
|
+
createCategory("forms", "Forms", [
|
|
307
|
+
createOption("web-test-opt1", "Toggle Skill", { selected: true })
|
|
308
|
+
])
|
|
309
|
+
];
|
|
310
|
+
const { lastFrame: frame2, unmount: unmount2 } = renderGrid({ categories: categories2 });
|
|
311
|
+
cleanup = unmount2;
|
|
312
|
+
const output2 = frame2();
|
|
313
|
+
globalExpect(output1).toContain(UI_SYMBOLS.UNSELECTED);
|
|
314
|
+
globalExpect(output1).not.toContain(UI_SYMBOLS.SELECTED);
|
|
315
|
+
globalExpect(output2).toContain(UI_SYMBOLS.SELECTED);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
describe("locked sections", () => {
|
|
319
|
+
it("should show all categories including locked ones", () => {
|
|
320
|
+
const { lastFrame, unmount } = renderGrid();
|
|
321
|
+
cleanup = unmount;
|
|
322
|
+
const output = lastFrame();
|
|
323
|
+
globalExpect(output).toContain("Framework");
|
|
324
|
+
globalExpect(output).toContain("Styling");
|
|
325
|
+
globalExpect(output).toContain("Client State");
|
|
326
|
+
});
|
|
327
|
+
it("should unlock sections when framework is selected", () => {
|
|
328
|
+
const { lastFrame, unmount } = renderGrid({
|
|
329
|
+
categories: categoriesWithFramework
|
|
330
|
+
});
|
|
331
|
+
cleanup = unmount;
|
|
332
|
+
const output = lastFrame();
|
|
333
|
+
globalExpect(output).toContain("Framework");
|
|
334
|
+
globalExpect(output).toContain("Styling");
|
|
335
|
+
globalExpect(output).toContain("Client State");
|
|
336
|
+
});
|
|
337
|
+
it("should not lock any sections when no framework category exists", () => {
|
|
338
|
+
const categoriesNoFramework = [
|
|
339
|
+
createCategory("styling", "Styling", [
|
|
340
|
+
createOption("web-test-scss", "SCSS"),
|
|
341
|
+
createOption("web-test-tailwind", "Tailwind")
|
|
342
|
+
]),
|
|
343
|
+
createCategory("client-state", "State", [createOption("web-test-zustand", "Zustand")])
|
|
344
|
+
];
|
|
345
|
+
const { lastFrame, unmount } = renderGrid({
|
|
346
|
+
categories: categoriesNoFramework
|
|
347
|
+
});
|
|
348
|
+
cleanup = unmount;
|
|
349
|
+
const output = lastFrame();
|
|
350
|
+
globalExpect(output).toContain("Styling");
|
|
351
|
+
globalExpect(output).toContain("State");
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
describe("focus indicator", () => {
|
|
355
|
+
it("should render focused option with label text", () => {
|
|
356
|
+
const { lastFrame, unmount } = renderGrid({
|
|
357
|
+
defaultFocusedRow: 0,
|
|
358
|
+
defaultFocusedCol: 0
|
|
359
|
+
});
|
|
360
|
+
cleanup = unmount;
|
|
361
|
+
const output = lastFrame();
|
|
362
|
+
globalExpect(output).toContain("React");
|
|
363
|
+
});
|
|
364
|
+
it("should render correctly when focusedRow changes", () => {
|
|
365
|
+
const { lastFrame: frame1, unmount: unmount1 } = renderGrid({
|
|
366
|
+
categories: categoriesWithFramework,
|
|
367
|
+
defaultFocusedRow: 0,
|
|
368
|
+
defaultFocusedCol: 0
|
|
369
|
+
});
|
|
370
|
+
const output1 = frame1();
|
|
371
|
+
unmount1();
|
|
372
|
+
const { lastFrame: frame2, unmount: unmount2 } = renderGrid({
|
|
373
|
+
categories: categoriesWithFramework,
|
|
374
|
+
defaultFocusedRow: 1,
|
|
375
|
+
defaultFocusedCol: 0
|
|
376
|
+
});
|
|
377
|
+
cleanup = unmount2;
|
|
378
|
+
const output2 = frame2();
|
|
379
|
+
globalExpect(output1).toContain("Framework");
|
|
380
|
+
globalExpect(output2).toContain("Styling");
|
|
381
|
+
});
|
|
382
|
+
it("should highlight focused category name", () => {
|
|
383
|
+
const { lastFrame, unmount } = renderGrid({
|
|
384
|
+
categories: categoriesWithFramework,
|
|
385
|
+
defaultFocusedRow: 1,
|
|
386
|
+
defaultFocusedCol: 0
|
|
387
|
+
});
|
|
388
|
+
cleanup = unmount;
|
|
389
|
+
const output = lastFrame();
|
|
390
|
+
globalExpect(output).toContain("Styling");
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
describe("keyboard navigation - arrow keys", () => {
|
|
394
|
+
it("should call onFocusChange when pressing left arrow", async () => {
|
|
395
|
+
const onFocusChange = vi.fn();
|
|
396
|
+
const { stdin, unmount } = renderGrid({
|
|
397
|
+
defaultFocusedRow: 0,
|
|
398
|
+
defaultFocusedCol: 1,
|
|
399
|
+
onFocusChange
|
|
400
|
+
});
|
|
401
|
+
cleanup = unmount;
|
|
402
|
+
await delay(RENDER_DELAY_MS);
|
|
403
|
+
await stdin.write(ARROW_LEFT);
|
|
404
|
+
await delay(INPUT_DELAY_MS);
|
|
405
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
406
|
+
});
|
|
407
|
+
it("should call onFocusChange when pressing right arrow", async () => {
|
|
408
|
+
const onFocusChange = vi.fn();
|
|
409
|
+
const { stdin, unmount } = renderGrid({
|
|
410
|
+
defaultFocusedRow: 0,
|
|
411
|
+
defaultFocusedCol: 0,
|
|
412
|
+
onFocusChange
|
|
413
|
+
});
|
|
414
|
+
cleanup = unmount;
|
|
415
|
+
await delay(RENDER_DELAY_MS);
|
|
416
|
+
await stdin.write(ARROW_RIGHT);
|
|
417
|
+
await delay(INPUT_DELAY_MS);
|
|
418
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 1);
|
|
419
|
+
});
|
|
420
|
+
it("should call onFocusChange when pressing up arrow (wraps to framework when locked)", async () => {
|
|
421
|
+
const onFocusChange = vi.fn();
|
|
422
|
+
const { stdin, unmount } = renderGrid({
|
|
423
|
+
defaultFocusedRow: 0,
|
|
424
|
+
defaultFocusedCol: 0,
|
|
425
|
+
onFocusChange
|
|
426
|
+
});
|
|
427
|
+
cleanup = unmount;
|
|
428
|
+
await delay(RENDER_DELAY_MS);
|
|
429
|
+
await stdin.write(ARROW_UP);
|
|
430
|
+
await delay(INPUT_DELAY_MS);
|
|
431
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
432
|
+
});
|
|
433
|
+
it("should navigate between sections when unlocked", async () => {
|
|
434
|
+
const onFocusChange = vi.fn();
|
|
435
|
+
const { stdin, unmount } = renderGrid({
|
|
436
|
+
categories: categoriesWithFramework,
|
|
437
|
+
defaultFocusedRow: 0,
|
|
438
|
+
defaultFocusedCol: 0,
|
|
439
|
+
onFocusChange
|
|
440
|
+
});
|
|
441
|
+
cleanup = unmount;
|
|
442
|
+
await delay(RENDER_DELAY_MS);
|
|
443
|
+
await stdin.write(ARROW_DOWN);
|
|
444
|
+
await delay(INPUT_DELAY_MS);
|
|
445
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
|
|
446
|
+
});
|
|
447
|
+
it("should wrap horizontally when pressing left at first column", async () => {
|
|
448
|
+
const onFocusChange = vi.fn();
|
|
449
|
+
const { stdin, unmount } = renderGrid({
|
|
450
|
+
defaultFocusedRow: 0,
|
|
451
|
+
defaultFocusedCol: 0,
|
|
452
|
+
onFocusChange
|
|
453
|
+
});
|
|
454
|
+
cleanup = unmount;
|
|
455
|
+
await delay(RENDER_DELAY_MS);
|
|
456
|
+
await stdin.write(ARROW_LEFT);
|
|
457
|
+
await delay(INPUT_DELAY_MS);
|
|
458
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 3);
|
|
459
|
+
});
|
|
460
|
+
it("should wrap horizontally when pressing right at last column", async () => {
|
|
461
|
+
const onFocusChange = vi.fn();
|
|
462
|
+
const { stdin, unmount } = renderGrid({
|
|
463
|
+
defaultFocusedRow: 0,
|
|
464
|
+
defaultFocusedCol: 3,
|
|
465
|
+
// Last option in framework
|
|
466
|
+
onFocusChange
|
|
467
|
+
});
|
|
468
|
+
cleanup = unmount;
|
|
469
|
+
await delay(RENDER_DELAY_MS);
|
|
470
|
+
await stdin.write(ARROW_RIGHT);
|
|
471
|
+
await delay(INPUT_DELAY_MS);
|
|
472
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
473
|
+
});
|
|
474
|
+
it("should wrap vertically when all sections are unlocked", async () => {
|
|
475
|
+
const onFocusChange = vi.fn();
|
|
476
|
+
const { stdin, unmount } = renderGrid({
|
|
477
|
+
categories: categoriesWithFramework,
|
|
478
|
+
defaultFocusedRow: 0,
|
|
479
|
+
defaultFocusedCol: 0,
|
|
480
|
+
onFocusChange
|
|
481
|
+
});
|
|
482
|
+
cleanup = unmount;
|
|
483
|
+
await delay(RENDER_DELAY_MS);
|
|
484
|
+
await stdin.write(ARROW_UP);
|
|
485
|
+
await delay(INPUT_DELAY_MS);
|
|
486
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(2, 0);
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
describe("keyboard navigation - vim keys", () => {
|
|
490
|
+
it("should move left with h key", async () => {
|
|
491
|
+
const onFocusChange = vi.fn();
|
|
492
|
+
const { stdin, unmount } = renderGrid({
|
|
493
|
+
defaultFocusedRow: 0,
|
|
494
|
+
defaultFocusedCol: 1,
|
|
495
|
+
onFocusChange
|
|
496
|
+
});
|
|
497
|
+
cleanup = unmount;
|
|
498
|
+
await delay(RENDER_DELAY_MS);
|
|
499
|
+
await stdin.write("h");
|
|
500
|
+
await delay(INPUT_DELAY_MS);
|
|
501
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
502
|
+
});
|
|
503
|
+
it("should move right with l key", async () => {
|
|
504
|
+
const onFocusChange = vi.fn();
|
|
505
|
+
const { stdin, unmount } = renderGrid({
|
|
506
|
+
defaultFocusedRow: 0,
|
|
507
|
+
defaultFocusedCol: 0,
|
|
508
|
+
onFocusChange
|
|
509
|
+
});
|
|
510
|
+
cleanup = unmount;
|
|
511
|
+
await delay(RENDER_DELAY_MS);
|
|
512
|
+
await stdin.write("l");
|
|
513
|
+
await delay(INPUT_DELAY_MS);
|
|
514
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 1);
|
|
515
|
+
});
|
|
516
|
+
it("should move up with k key", async () => {
|
|
517
|
+
const onFocusChange = vi.fn();
|
|
518
|
+
const { stdin, unmount } = renderGrid({
|
|
519
|
+
categories: categoriesWithFramework,
|
|
520
|
+
defaultFocusedRow: 1,
|
|
521
|
+
defaultFocusedCol: 0,
|
|
522
|
+
onFocusChange
|
|
523
|
+
});
|
|
524
|
+
cleanup = unmount;
|
|
525
|
+
await delay(RENDER_DELAY_MS);
|
|
526
|
+
await stdin.write("k");
|
|
527
|
+
await delay(INPUT_DELAY_MS);
|
|
528
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
529
|
+
});
|
|
530
|
+
it("should move down with j key", async () => {
|
|
531
|
+
const onFocusChange = vi.fn();
|
|
532
|
+
const { stdin, unmount } = renderGrid({
|
|
533
|
+
categories: categoriesWithFramework,
|
|
534
|
+
defaultFocusedRow: 0,
|
|
535
|
+
defaultFocusedCol: 0,
|
|
536
|
+
onFocusChange
|
|
537
|
+
});
|
|
538
|
+
cleanup = unmount;
|
|
539
|
+
await delay(RENDER_DELAY_MS);
|
|
540
|
+
await stdin.write("j");
|
|
541
|
+
await delay(INPUT_DELAY_MS);
|
|
542
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
describe("selection toggle", () => {
|
|
546
|
+
it("should call onToggle when pressing space on a normal option", async () => {
|
|
547
|
+
const onToggle = vi.fn();
|
|
548
|
+
const { stdin, unmount } = renderGrid({
|
|
549
|
+
defaultFocusedRow: 0,
|
|
550
|
+
defaultFocusedCol: 1,
|
|
551
|
+
// vue (normal state)
|
|
552
|
+
onToggle
|
|
553
|
+
});
|
|
554
|
+
cleanup = unmount;
|
|
555
|
+
await delay(RENDER_DELAY_MS);
|
|
556
|
+
await stdin.write(" ");
|
|
557
|
+
await delay(INPUT_DELAY_MS);
|
|
558
|
+
globalExpect(onToggle).toHaveBeenCalledWith("framework", "web-test-vue");
|
|
559
|
+
});
|
|
560
|
+
it("should call onToggle when pressing space on a selected option", async () => {
|
|
561
|
+
const onToggle = vi.fn();
|
|
562
|
+
const categories = [
|
|
563
|
+
createCategory(
|
|
564
|
+
"framework",
|
|
565
|
+
"Framework",
|
|
566
|
+
[
|
|
567
|
+
createOption("web-test-react", "React", { selected: true }),
|
|
568
|
+
createOption("web-test-vue", "Vue")
|
|
569
|
+
],
|
|
570
|
+
{ required: true }
|
|
571
|
+
)
|
|
572
|
+
];
|
|
573
|
+
const { stdin, unmount } = renderGrid({
|
|
574
|
+
categories,
|
|
575
|
+
defaultFocusedRow: 0,
|
|
576
|
+
defaultFocusedCol: 0,
|
|
577
|
+
// react (selected)
|
|
578
|
+
expertMode: true,
|
|
579
|
+
onToggle
|
|
580
|
+
});
|
|
581
|
+
cleanup = unmount;
|
|
582
|
+
await delay(RENDER_DELAY_MS);
|
|
583
|
+
await stdin.write(" ");
|
|
584
|
+
await delay(INPUT_DELAY_MS);
|
|
585
|
+
globalExpect(onToggle).toHaveBeenCalledWith("framework", "web-test-react");
|
|
586
|
+
});
|
|
587
|
+
it("should NOT call onToggle when all options in a category are disabled", async () => {
|
|
588
|
+
const onToggle = vi.fn();
|
|
589
|
+
const categories = [
|
|
590
|
+
createCategory("testing", "Test", [
|
|
591
|
+
createOption("web-test-opt1", "Option 1", { state: "disabled" }),
|
|
592
|
+
createOption("web-test-opt2", "Option 2", { state: "disabled" })
|
|
593
|
+
])
|
|
594
|
+
];
|
|
595
|
+
const { stdin, unmount } = renderGrid({
|
|
596
|
+
categories,
|
|
597
|
+
defaultFocusedRow: 0,
|
|
598
|
+
defaultFocusedCol: 0,
|
|
599
|
+
expertMode: true,
|
|
600
|
+
onToggle
|
|
601
|
+
});
|
|
602
|
+
cleanup = unmount;
|
|
603
|
+
await delay(RENDER_DELAY_MS);
|
|
604
|
+
await stdin.write(" ");
|
|
605
|
+
await delay(INPUT_DELAY_MS);
|
|
606
|
+
globalExpect(onToggle).not.toHaveBeenCalled();
|
|
607
|
+
});
|
|
608
|
+
it("should bounce focus away from locked sections on mount", async () => {
|
|
609
|
+
const onFocusChange = vi.fn();
|
|
610
|
+
const { unmount } = renderGrid({
|
|
611
|
+
defaultFocusedRow: 1,
|
|
612
|
+
// Styling (locked)
|
|
613
|
+
defaultFocusedCol: 0,
|
|
614
|
+
onFocusChange
|
|
615
|
+
});
|
|
616
|
+
cleanup = unmount;
|
|
617
|
+
await delay(RENDER_DELAY_MS);
|
|
618
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
619
|
+
});
|
|
620
|
+
});
|
|
621
|
+
describe("disabled options navigation", () => {
|
|
622
|
+
it("should skip disabled options when navigating right", async () => {
|
|
623
|
+
const onFocusChange = vi.fn();
|
|
624
|
+
const categories = [
|
|
625
|
+
createCategory("testing", "Test", [
|
|
626
|
+
createOption("web-test-opt1", "Option 1"),
|
|
627
|
+
createOption("web-test-opt2", "Option 2", { state: "disabled" }),
|
|
628
|
+
createOption("web-test-opt3", "Option 3")
|
|
629
|
+
])
|
|
630
|
+
];
|
|
631
|
+
const { stdin, unmount } = renderGrid({
|
|
632
|
+
categories,
|
|
633
|
+
defaultFocusedRow: 0,
|
|
634
|
+
defaultFocusedCol: 0,
|
|
635
|
+
expertMode: true,
|
|
636
|
+
onFocusChange
|
|
637
|
+
});
|
|
638
|
+
cleanup = unmount;
|
|
639
|
+
await delay(RENDER_DELAY_MS);
|
|
640
|
+
await stdin.write(ARROW_RIGHT);
|
|
641
|
+
await delay(INPUT_DELAY_MS);
|
|
642
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 2);
|
|
643
|
+
});
|
|
644
|
+
it("should skip disabled options when navigating left", async () => {
|
|
645
|
+
const onFocusChange = vi.fn();
|
|
646
|
+
const categories = [
|
|
647
|
+
createCategory("testing", "Test", [
|
|
648
|
+
createOption("web-test-opt1", "Option 1"),
|
|
649
|
+
createOption("web-test-opt2", "Option 2", { state: "disabled" }),
|
|
650
|
+
createOption("web-test-opt3", "Option 3")
|
|
651
|
+
])
|
|
652
|
+
];
|
|
653
|
+
const { stdin, unmount } = renderGrid({
|
|
654
|
+
categories,
|
|
655
|
+
defaultFocusedRow: 0,
|
|
656
|
+
defaultFocusedCol: 2,
|
|
657
|
+
// Start at opt3
|
|
658
|
+
expertMode: true,
|
|
659
|
+
onFocusChange
|
|
660
|
+
});
|
|
661
|
+
cleanup = unmount;
|
|
662
|
+
await delay(RENDER_DELAY_MS);
|
|
663
|
+
await stdin.write(ARROW_LEFT);
|
|
664
|
+
await delay(INPUT_DELAY_MS);
|
|
665
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
666
|
+
});
|
|
667
|
+
it("should handle all options disabled in a row", async () => {
|
|
668
|
+
const onFocusChange = vi.fn();
|
|
669
|
+
const categories = [
|
|
670
|
+
createCategory("testing", "Test", [
|
|
671
|
+
createOption("web-test-opt1", "Option 1", { state: "disabled" }),
|
|
672
|
+
createOption("web-test-opt2", "Option 2", { state: "disabled" })
|
|
673
|
+
])
|
|
674
|
+
];
|
|
675
|
+
const { stdin, unmount } = renderGrid({
|
|
676
|
+
categories,
|
|
677
|
+
defaultFocusedRow: 0,
|
|
678
|
+
defaultFocusedCol: 0,
|
|
679
|
+
expertMode: true,
|
|
680
|
+
onFocusChange
|
|
681
|
+
});
|
|
682
|
+
cleanup = unmount;
|
|
683
|
+
await delay(RENDER_DELAY_MS);
|
|
684
|
+
await stdin.write(ARROW_RIGHT);
|
|
685
|
+
await delay(INPUT_DELAY_MS);
|
|
686
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
describe("exclusive categories", () => {
|
|
690
|
+
it("should render exclusive category correctly", () => {
|
|
691
|
+
const { lastFrame, unmount } = renderGrid();
|
|
692
|
+
cleanup = unmount;
|
|
693
|
+
const output = lastFrame();
|
|
694
|
+
globalExpect(output).toContain("Framework");
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
describe("tab navigation", () => {
|
|
698
|
+
it("should jump to next section when pressing Tab", async () => {
|
|
699
|
+
const onFocusChange = vi.fn();
|
|
700
|
+
const { stdin, unmount } = renderGrid({
|
|
701
|
+
categories: categoriesWithFramework,
|
|
702
|
+
defaultFocusedRow: 0,
|
|
703
|
+
defaultFocusedCol: 0,
|
|
704
|
+
onFocusChange
|
|
705
|
+
});
|
|
706
|
+
cleanup = unmount;
|
|
707
|
+
await delay(RENDER_DELAY_MS);
|
|
708
|
+
await stdin.write(TAB);
|
|
709
|
+
await delay(INPUT_DELAY_MS);
|
|
710
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
|
|
711
|
+
});
|
|
712
|
+
it("should only jump to unlocked sections", async () => {
|
|
713
|
+
const onFocusChange = vi.fn();
|
|
714
|
+
const { stdin, unmount } = renderGrid({
|
|
715
|
+
defaultFocusedRow: 0,
|
|
716
|
+
defaultFocusedCol: 0,
|
|
717
|
+
onFocusChange
|
|
718
|
+
});
|
|
719
|
+
cleanup = unmount;
|
|
720
|
+
await delay(RENDER_DELAY_MS);
|
|
721
|
+
await stdin.write(TAB);
|
|
722
|
+
await delay(INPUT_DELAY_MS);
|
|
723
|
+
globalExpect(onFocusChange).not.toHaveBeenCalled();
|
|
724
|
+
});
|
|
725
|
+
});
|
|
726
|
+
describe("show descriptions toggle", () => {
|
|
727
|
+
it("should call onToggleDescriptions when pressing d key", async () => {
|
|
728
|
+
const onToggleDescriptions = vi.fn();
|
|
729
|
+
const { stdin, unmount } = renderGrid({
|
|
730
|
+
onToggleDescriptions
|
|
731
|
+
});
|
|
732
|
+
cleanup = unmount;
|
|
733
|
+
await delay(RENDER_DELAY_MS);
|
|
734
|
+
await stdin.write("d");
|
|
735
|
+
await delay(INPUT_DELAY_MS);
|
|
736
|
+
globalExpect(onToggleDescriptions).toHaveBeenCalled();
|
|
737
|
+
});
|
|
738
|
+
it("should show descriptions when showDescriptions is true", () => {
|
|
739
|
+
const { lastFrame, unmount } = renderGrid({ showDescriptions: true });
|
|
740
|
+
cleanup = unmount;
|
|
741
|
+
const output = lastFrame();
|
|
742
|
+
globalExpect(output).toContain("Popular choice");
|
|
743
|
+
});
|
|
744
|
+
it("should hide descriptions when showDescriptions is false", () => {
|
|
745
|
+
const { lastFrame, unmount } = renderGrid({ showDescriptions: false });
|
|
746
|
+
cleanup = unmount;
|
|
747
|
+
const output = lastFrame();
|
|
748
|
+
globalExpect(output).toBeDefined();
|
|
749
|
+
});
|
|
750
|
+
it("should show descriptions when enabled", () => {
|
|
751
|
+
const { lastFrame, unmount } = renderGrid({
|
|
752
|
+
showDescriptions: true
|
|
753
|
+
});
|
|
754
|
+
cleanup = unmount;
|
|
755
|
+
const output = lastFrame();
|
|
756
|
+
globalExpect(output).toContain("Popular choice");
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
describe("expert mode", () => {
|
|
760
|
+
it("should not handle expert mode toggle locally (handled globally)", () => {
|
|
761
|
+
const { lastFrame, unmount } = renderGrid();
|
|
762
|
+
cleanup = unmount;
|
|
763
|
+
const output = lastFrame();
|
|
764
|
+
globalExpect(output).not.toContain("[e] Expert Mode");
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
describe("option ordering", () => {
|
|
768
|
+
it("should sort options by state when expertMode is false", () => {
|
|
769
|
+
const { lastFrame, unmount } = renderGrid({ expertMode: false });
|
|
770
|
+
cleanup = unmount;
|
|
771
|
+
const output = lastFrame();
|
|
772
|
+
globalExpect(output).toBeDefined();
|
|
773
|
+
});
|
|
774
|
+
it("should preserve original order when expertMode is true", () => {
|
|
775
|
+
const { lastFrame, unmount } = renderGrid({ expertMode: true });
|
|
776
|
+
cleanup = unmount;
|
|
777
|
+
const output = lastFrame();
|
|
778
|
+
globalExpect(output).toBeDefined();
|
|
779
|
+
});
|
|
780
|
+
});
|
|
781
|
+
describe("edge cases", () => {
|
|
782
|
+
it("should handle single category", () => {
|
|
783
|
+
const categories = [
|
|
784
|
+
createCategory("forms", "Single Category", [createOption("web-test-opt1", "Option 1")])
|
|
785
|
+
];
|
|
786
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
787
|
+
cleanup = unmount;
|
|
788
|
+
const output = lastFrame();
|
|
789
|
+
globalExpect(output).toContain("Single Category");
|
|
790
|
+
globalExpect(output).toContain("Option 1");
|
|
791
|
+
});
|
|
792
|
+
it("should handle single option in category", () => {
|
|
793
|
+
const categories = [
|
|
794
|
+
createCategory("forms", "Single", [createOption("web-test-only", "Only Option")])
|
|
795
|
+
];
|
|
796
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
797
|
+
cleanup = unmount;
|
|
798
|
+
const output = lastFrame();
|
|
799
|
+
globalExpect(output).toContain("Only Option");
|
|
800
|
+
});
|
|
801
|
+
it("should handle category with many options (flows naturally)", () => {
|
|
802
|
+
const options = Array.from(
|
|
803
|
+
{ length: 10 },
|
|
804
|
+
(_, i) => createOption(`web-test-opt${i}`, `Option ${i}`)
|
|
805
|
+
);
|
|
806
|
+
const categories = [createCategory("mocking", "Many Options", options)];
|
|
807
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
808
|
+
cleanup = unmount;
|
|
809
|
+
const output = lastFrame();
|
|
810
|
+
globalExpect(output).toContain("Many Options");
|
|
811
|
+
globalExpect(output).toContain("Option 0");
|
|
812
|
+
globalExpect(output).toContain("Option 9");
|
|
813
|
+
});
|
|
814
|
+
it("should handle long option labels", () => {
|
|
815
|
+
const categories = [
|
|
816
|
+
createCategory("i18n", "Long Labels", [
|
|
817
|
+
createOption("web-test-long1", "Very Long Option Name"),
|
|
818
|
+
createOption("web-test-long2", "Another Long Name")
|
|
819
|
+
])
|
|
820
|
+
];
|
|
821
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
822
|
+
cleanup = unmount;
|
|
823
|
+
const output = lastFrame();
|
|
824
|
+
globalExpect(output).toContain("Very Long Option Name");
|
|
825
|
+
});
|
|
826
|
+
it("should handle categories with different option counts", () => {
|
|
827
|
+
const categories = [
|
|
828
|
+
createCategory("framework", "Category 1", [
|
|
829
|
+
createOption("web-test-opt1", "Option 1"),
|
|
830
|
+
createOption("web-test-opt2", "Option 2")
|
|
831
|
+
]),
|
|
832
|
+
createCategory("styling", "Category 2", [createOption("web-test-opt3", "Option 3")]),
|
|
833
|
+
createCategory("client-state", "Category 3", [
|
|
834
|
+
createOption("web-test-opt4", "Option 4"),
|
|
835
|
+
createOption("web-test-opt5", "Option 5"),
|
|
836
|
+
createOption("web-test-opt6", "Option 6")
|
|
837
|
+
])
|
|
838
|
+
];
|
|
839
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
840
|
+
cleanup = unmount;
|
|
841
|
+
const output = lastFrame();
|
|
842
|
+
globalExpect(output).toContain("Category 1");
|
|
843
|
+
globalExpect(output).toContain("Category 2");
|
|
844
|
+
globalExpect(output).toContain("Category 3");
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
describe("column adjustment", () => {
|
|
848
|
+
it("should adjust focusedCol when changing to row with fewer options", async () => {
|
|
849
|
+
const onFocusChange = vi.fn();
|
|
850
|
+
const categories = [
|
|
851
|
+
createCategory(
|
|
852
|
+
"framework",
|
|
853
|
+
"Framework",
|
|
854
|
+
[
|
|
855
|
+
createOption("web-test-opt1", "Option 1", { selected: true }),
|
|
856
|
+
// Framework selected
|
|
857
|
+
createOption("web-test-opt2", "Option 2"),
|
|
858
|
+
createOption("web-test-opt3", "Option 3")
|
|
859
|
+
],
|
|
860
|
+
{ required: true }
|
|
861
|
+
),
|
|
862
|
+
createCategory("styling", "Category 2", [createOption("web-test-opt4", "Option 4")])
|
|
863
|
+
];
|
|
864
|
+
const { stdin, unmount } = renderGrid({
|
|
865
|
+
categories,
|
|
866
|
+
defaultFocusedRow: 0,
|
|
867
|
+
defaultFocusedCol: 2,
|
|
868
|
+
// Last option in first row
|
|
869
|
+
onFocusChange
|
|
870
|
+
});
|
|
871
|
+
cleanup = unmount;
|
|
872
|
+
await delay(RENDER_DELAY_MS);
|
|
873
|
+
await stdin.write(ARROW_DOWN);
|
|
874
|
+
await delay(INPUT_DELAY_MS);
|
|
875
|
+
globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
|
|
876
|
+
});
|
|
877
|
+
});
|
|
878
|
+
describe("installed indicator", () => {
|
|
879
|
+
it("should show checkmark for installed skill", () => {
|
|
880
|
+
const categories = [
|
|
881
|
+
createCategory("forms", "Forms", [
|
|
882
|
+
createOption("web-test-opt1", "Option 1", { installed: true })
|
|
883
|
+
])
|
|
884
|
+
];
|
|
885
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
886
|
+
cleanup = unmount;
|
|
887
|
+
const output = lastFrame();
|
|
888
|
+
globalExpect(output).toContain("\u2713");
|
|
889
|
+
globalExpect(output).toContain("Option 1");
|
|
890
|
+
});
|
|
891
|
+
it("should NOT show checkmark for non-installed skill", () => {
|
|
892
|
+
const categories = [
|
|
893
|
+
createCategory("forms", "Forms", [createOption("web-test-opt1", "Option 1")])
|
|
894
|
+
];
|
|
895
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
896
|
+
cleanup = unmount;
|
|
897
|
+
const output = lastFrame();
|
|
898
|
+
globalExpect(output).not.toContain("\u2713");
|
|
899
|
+
globalExpect(output).toContain("Option 1");
|
|
900
|
+
});
|
|
901
|
+
it("should show both checkmark and cyan styling when installed and selected", () => {
|
|
902
|
+
const categories = [
|
|
903
|
+
createCategory("forms", "Forms", [
|
|
904
|
+
createOption("web-test-opt1", "Option 1", { installed: true, selected: true })
|
|
905
|
+
])
|
|
906
|
+
];
|
|
907
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
908
|
+
cleanup = unmount;
|
|
909
|
+
const output = lastFrame();
|
|
910
|
+
globalExpect(output).toContain("\u2713");
|
|
911
|
+
globalExpect(output).toContain("Option 1");
|
|
912
|
+
});
|
|
913
|
+
it("should show both L badge and checkmark when local and installed", () => {
|
|
914
|
+
const categories = [
|
|
915
|
+
createCategory("forms", "Forms", [
|
|
916
|
+
createOption("web-test-opt1", "Option 1", { local: true, installed: true })
|
|
917
|
+
])
|
|
918
|
+
];
|
|
919
|
+
const { lastFrame, unmount } = renderGrid({ categories });
|
|
920
|
+
cleanup = unmount;
|
|
921
|
+
const output = lastFrame();
|
|
922
|
+
globalExpect(output).toContain("L");
|
|
923
|
+
globalExpect(output).toContain("\u2713");
|
|
924
|
+
globalExpect(output).toContain("Option 1");
|
|
925
|
+
});
|
|
926
|
+
});
|
|
927
|
+
describe("scroll viewport", () => {
|
|
928
|
+
it("should render all categories when no height constraint", () => {
|
|
929
|
+
const { lastFrame, unmount } = renderGrid();
|
|
930
|
+
cleanup = unmount;
|
|
931
|
+
const output = lastFrame();
|
|
932
|
+
globalExpect(output).toContain("Framework");
|
|
933
|
+
globalExpect(output).toContain("Styling");
|
|
934
|
+
globalExpect(output).toContain("Client State");
|
|
935
|
+
globalExpect(output).toContain("Server State");
|
|
936
|
+
globalExpect(output).toContain("Analytics");
|
|
937
|
+
globalExpect(output).not.toContain("more categories");
|
|
938
|
+
});
|
|
939
|
+
it("should render scroll indicators when height is constrained", () => {
|
|
940
|
+
const manyCategories = Array.from(
|
|
941
|
+
{ length: 8 },
|
|
942
|
+
(_, i) => createCategory(`cat-${i}`, `Category ${i}`, [
|
|
943
|
+
createOption(`web-test-opt${i}-a`, `Option ${i}A`),
|
|
944
|
+
createOption(`web-test-opt${i}-b`, `Option ${i}B`),
|
|
945
|
+
createOption(`web-test-opt${i}-c`, `Option ${i}C`)
|
|
946
|
+
])
|
|
947
|
+
);
|
|
948
|
+
const { lastFrame, unmount } = renderGrid({
|
|
949
|
+
categories: manyCategories,
|
|
950
|
+
availableHeight: 8,
|
|
951
|
+
terminalWidth: 120
|
|
952
|
+
});
|
|
953
|
+
cleanup = unmount;
|
|
954
|
+
const output = lastFrame();
|
|
955
|
+
globalExpect(output).toContain("more categories below");
|
|
956
|
+
});
|
|
957
|
+
it("should not render scroll indicators when all content fits", () => {
|
|
958
|
+
const categories = [
|
|
959
|
+
createCategory("forms", "Forms", [createOption("web-test-opt1", "A")])
|
|
960
|
+
];
|
|
961
|
+
const { lastFrame, unmount } = renderGrid({
|
|
962
|
+
categories,
|
|
963
|
+
availableHeight: 100,
|
|
964
|
+
terminalWidth: 120
|
|
965
|
+
});
|
|
966
|
+
cleanup = unmount;
|
|
967
|
+
globalExpect(lastFrame()).not.toContain("more categories");
|
|
968
|
+
});
|
|
969
|
+
it("should keep focused category visible when scrolling down", async () => {
|
|
970
|
+
const onFocusChange = vi.fn();
|
|
971
|
+
const manyCategories = Array.from(
|
|
972
|
+
{ length: 6 },
|
|
973
|
+
(_, i) => createCategory(`cat-${i}`, `Category ${i}`, [
|
|
974
|
+
createOption(`web-test-opt${i}-a`, `Option ${i}A`)
|
|
975
|
+
])
|
|
976
|
+
);
|
|
977
|
+
const { stdin, lastFrame, unmount } = renderGrid({
|
|
978
|
+
categories: manyCategories,
|
|
979
|
+
availableHeight: 8,
|
|
980
|
+
terminalWidth: 120,
|
|
981
|
+
defaultFocusedRow: 0,
|
|
982
|
+
onFocusChange
|
|
983
|
+
});
|
|
984
|
+
cleanup = unmount;
|
|
985
|
+
await delay(RENDER_DELAY_MS);
|
|
986
|
+
await stdin.write(ARROW_DOWN);
|
|
987
|
+
await delay(INPUT_DELAY_MS);
|
|
988
|
+
await stdin.write(ARROW_DOWN);
|
|
989
|
+
await delay(INPUT_DELAY_MS);
|
|
990
|
+
await stdin.write(ARROW_DOWN);
|
|
991
|
+
await delay(INPUT_DELAY_MS);
|
|
992
|
+
const output = lastFrame();
|
|
993
|
+
globalExpect(output).toContain("Category 3");
|
|
994
|
+
});
|
|
995
|
+
});
|
|
996
|
+
});
|
|
997
|
+
//# sourceMappingURL=category-grid.test.js.map
|