@agents-inc/cli 0.38.0 → 0.41.2
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 +77 -0
- package/README.md +1 -1
- package/config/skills-matrix.yaml +115 -123
- package/config/stacks.yaml +687 -687
- package/dist/{chunk-YHQNTBBN.js → chunk-2D6LKRHW.js} +2 -2
- package/dist/{chunk-CYFU3ARY.js → chunk-342YB6TQ.js} +15 -17
- package/dist/chunk-342YB6TQ.js.map +1 -0
- package/dist/{chunk-HRMQ2RGY.js → chunk-423MJ6DT.js} +31 -56
- package/dist/chunk-423MJ6DT.js.map +1 -0
- package/dist/{chunk-NFV4SKH5.js → chunk-4LT6RXMY.js} +4 -4
- package/dist/{chunk-IVIK776Y.js → chunk-4SYXPG7L.js} +2 -2
- package/dist/{chunk-DUQFF45G.js → chunk-4UTPJXUX.js} +8 -8
- package/dist/{chunk-3E2V5YL3.js → chunk-5TMB53BV.js} +3 -3
- package/dist/{chunk-NI2RSNWB.js → chunk-7FBM7V3E.js} +10 -22
- package/dist/chunk-7FBM7V3E.js.map +1 -0
- package/dist/chunk-ACVJVYMC.js +111 -0
- package/dist/chunk-ACVJVYMC.js.map +1 -0
- package/dist/{chunk-FWQK3HWB.js → chunk-AH7XHAKN.js} +11 -11
- package/dist/chunk-AH7XHAKN.js.map +1 -0
- package/dist/{chunk-VAHVSQIG.js → chunk-AVVYFEMF.js} +2 -2
- package/dist/{chunk-EISBUEBL.js → chunk-BFISETQG.js} +3 -3
- package/dist/{chunk-ZBJQXDQN.js → chunk-BK7TANUV.js} +4 -2
- package/dist/chunk-BK7TANUV.js.map +1 -0
- package/dist/{chunk-VAK5PX72.js → chunk-DV4ALU5I.js} +6 -6
- package/dist/{chunk-OEX5JDQD.js → chunk-FHBICUXB.js} +4 -4
- package/dist/{chunk-TA6IIQI4.js → chunk-GEDWVX6Y.js} +3 -3
- package/dist/chunk-GEDWVX6Y.js.map +1 -0
- package/dist/{chunk-M6PGIZNS.js → chunk-H6H3COI5.js} +5 -5
- package/dist/{chunk-54ZZCWN4.js → chunk-KC2SIUIA.js} +3 -8
- package/dist/chunk-KC2SIUIA.js.map +1 -0
- package/dist/{chunk-2XX4TMCI.js → chunk-KXM7KOPE.js} +2 -2
- package/dist/{chunk-HKDE4LJW.js → chunk-LJRP4SWY.js} +6 -5
- package/dist/chunk-LJRP4SWY.js.map +1 -0
- package/dist/{chunk-TBDIR6LY.js → chunk-MNPPGIZQ.js} +5 -5
- package/dist/{chunk-3NQJOJZL.js → chunk-NYP5SB2V.js} +2 -2
- package/dist/{chunk-UOMMQ5M6.js → chunk-NZYKDVRL.js} +2 -2
- package/dist/{chunk-UV6JUGIY.js → chunk-PURJZ72D.js} +2 -2
- package/dist/{chunk-ATLRUR3B.js → chunk-R52N7DBG.js} +2 -2
- package/dist/{chunk-WSGGJKD5.js → chunk-SILUTTV7.js} +6 -6
- package/dist/chunk-SILUTTV7.js.map +1 -0
- package/dist/{chunk-IZRVFC2Z.js → chunk-TJAZ7QCF.js} +4 -4
- package/dist/{chunk-U5OB5ADP.js → chunk-TTXV55NQ.js} +57 -16
- package/dist/chunk-TTXV55NQ.js.map +1 -0
- package/dist/{chunk-TY5GELDB.js → chunk-UKTYDNWJ.js} +2 -2
- package/dist/{chunk-HRW7BIDE.js → chunk-WS6OQIEN.js} +2 -2
- package/dist/{chunk-YJIJTBSX.js → chunk-XJXJZ2MJ.js} +42 -54
- package/dist/chunk-XJXJZ2MJ.js.map +1 -0
- package/dist/chunk-YLJYAQSG.js +210 -0
- package/dist/chunk-YLJYAQSG.js.map +1 -0
- package/dist/{chunk-MZB3GGOH.js → chunk-YRVTXSXP.js} +1 -2
- package/dist/chunk-YRVTXSXP.js.map +1 -0
- package/dist/{chunk-TNFACSWF.js → chunk-ZLHGJSRK.js} +3 -3
- package/dist/cli/defaults/agent-mappings.yaml +14 -70
- package/dist/commands/build/marketplace.js +3 -3
- package/dist/commands/build/plugins.js +5 -5
- package/dist/commands/build/stack.js +5 -5
- package/dist/commands/compile.js +8 -7
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +4 -4
- package/dist/commands/config/index.js +5 -5
- package/dist/commands/config/path.js +4 -4
- package/dist/commands/config/set-project.js +4 -4
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/config/unset-project.js +4 -4
- package/dist/commands/diff.js +8 -5
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +8 -7
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +33 -30
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +4 -4
- package/dist/commands/import/skill.js +5 -5
- package/dist/commands/info.js +7 -6
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +40 -32
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +6 -5
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +5 -5
- package/dist/commands/new/skill.js +8 -5
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +8 -5
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +7 -7
- package/dist/commands/uninstall.js +19 -7
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +8 -7
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +5 -5
- package/dist/commands/version/bump.js +4 -4
- package/dist/commands/version/index.js +4 -4
- package/dist/commands/version/set.js +4 -4
- package/dist/commands/version/show.js +4 -4
- package/dist/components/skill-search/skill-search.js +3 -3
- package/dist/components/wizard/category-grid.js +2 -2
- package/dist/components/wizard/category-grid.test.js +40 -40
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/checkbox-grid.js +2 -2
- package/dist/components/wizard/checkbox-grid.test.js +16 -6
- package/dist/components/wizard/checkbox-grid.test.js.map +1 -1
- package/dist/components/wizard/domain-selection.js +7 -7
- package/dist/components/wizard/help-modal.js +2 -2
- package/dist/components/wizard/menu-item.js +2 -2
- package/dist/components/wizard/search-modal.js +2 -2
- package/dist/components/wizard/search-modal.test.js +2 -2
- package/dist/components/wizard/section-progress.js +2 -2
- package/dist/components/wizard/section-progress.test.js +2 -2
- package/dist/components/wizard/source-grid.js +3 -3
- package/dist/components/wizard/source-grid.test.js +3 -3
- package/dist/components/wizard/stack-selection.js +9 -9
- package/dist/components/wizard/step-agents.js +7 -7
- package/dist/components/wizard/step-agents.test.js +24 -19
- package/dist/components/wizard/step-agents.test.js.map +1 -1
- package/dist/components/wizard/step-build.js +8 -8
- package/dist/components/wizard/step-build.test.js +40 -39
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +3 -3
- package/dist/components/wizard/step-confirm.test.js +19 -13
- package/dist/components/wizard/step-confirm.test.js.map +1 -1
- package/dist/components/wizard/step-refine.js +2 -2
- package/dist/components/wizard/step-refine.test.js +2 -2
- package/dist/components/wizard/step-settings.js +5 -5
- package/dist/components/wizard/step-settings.test.js +8 -8
- package/dist/components/wizard/step-sources.js +9 -9
- package/dist/components/wizard/step-sources.test.js +13 -13
- package/dist/components/wizard/step-sources.test.js.map +1 -1
- package/dist/components/wizard/step-stack.js +12 -12
- package/dist/components/wizard/step-stack.test.js +19 -21
- package/dist/components/wizard/step-stack.test.js.map +1 -1
- package/dist/components/wizard/view-title.js +2 -2
- package/dist/components/wizard/wizard-layout.js +8 -8
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard-tabs.test.js +2 -2
- package/dist/components/wizard/wizard.js +25 -25
- package/dist/config/skills-matrix.yaml +115 -123
- package/dist/config/stacks.yaml +687 -687
- package/dist/hooks/init.js +3 -3
- package/dist/{source-manager-FEGVYDFZ.js → source-manager-PPABS6BC.js} +4 -4
- package/dist/stores/wizard-store.js +5 -5
- package/dist/stores/wizard-store.test.js +115 -187
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +1 -1
- package/src/schemas/metadata.schema.json +41 -1
- package/src/schemas/project-config.schema.json +34 -35
- package/src/schemas/skills-matrix.schema.json +100 -101
- package/src/schemas/stacks.schema.json +34 -35
- package/dist/chunk-54ZZCWN4.js.map +0 -1
- package/dist/chunk-CYFU3ARY.js.map +0 -1
- package/dist/chunk-EXFVAEPY.js +0 -80
- package/dist/chunk-EXFVAEPY.js.map +0 -1
- package/dist/chunk-FWQK3HWB.js.map +0 -1
- package/dist/chunk-HKDE4LJW.js.map +0 -1
- package/dist/chunk-HRMQ2RGY.js.map +0 -1
- package/dist/chunk-IWNPFIGY.js +0 -110
- package/dist/chunk-IWNPFIGY.js.map +0 -1
- package/dist/chunk-MZB3GGOH.js.map +0 -1
- package/dist/chunk-NI2RSNWB.js.map +0 -1
- package/dist/chunk-TA6IIQI4.js.map +0 -1
- package/dist/chunk-U5OB5ADP.js.map +0 -1
- package/dist/chunk-WSGGJKD5.js.map +0 -1
- package/dist/chunk-YJIJTBSX.js.map +0 -1
- package/dist/chunk-ZBJQXDQN.js.map +0 -1
- /package/dist/{chunk-YHQNTBBN.js.map → chunk-2D6LKRHW.js.map} +0 -0
- /package/dist/{chunk-NFV4SKH5.js.map → chunk-4LT6RXMY.js.map} +0 -0
- /package/dist/{chunk-IVIK776Y.js.map → chunk-4SYXPG7L.js.map} +0 -0
- /package/dist/{chunk-DUQFF45G.js.map → chunk-4UTPJXUX.js.map} +0 -0
- /package/dist/{chunk-3E2V5YL3.js.map → chunk-5TMB53BV.js.map} +0 -0
- /package/dist/{chunk-VAHVSQIG.js.map → chunk-AVVYFEMF.js.map} +0 -0
- /package/dist/{chunk-EISBUEBL.js.map → chunk-BFISETQG.js.map} +0 -0
- /package/dist/{chunk-VAK5PX72.js.map → chunk-DV4ALU5I.js.map} +0 -0
- /package/dist/{chunk-OEX5JDQD.js.map → chunk-FHBICUXB.js.map} +0 -0
- /package/dist/{chunk-M6PGIZNS.js.map → chunk-H6H3COI5.js.map} +0 -0
- /package/dist/{chunk-2XX4TMCI.js.map → chunk-KXM7KOPE.js.map} +0 -0
- /package/dist/{chunk-TBDIR6LY.js.map → chunk-MNPPGIZQ.js.map} +0 -0
- /package/dist/{chunk-3NQJOJZL.js.map → chunk-NYP5SB2V.js.map} +0 -0
- /package/dist/{chunk-UOMMQ5M6.js.map → chunk-NZYKDVRL.js.map} +0 -0
- /package/dist/{chunk-UV6JUGIY.js.map → chunk-PURJZ72D.js.map} +0 -0
- /package/dist/{chunk-ATLRUR3B.js.map → chunk-R52N7DBG.js.map} +0 -0
- /package/dist/{chunk-IZRVFC2Z.js.map → chunk-TJAZ7QCF.js.map} +0 -0
- /package/dist/{chunk-TY5GELDB.js.map → chunk-UKTYDNWJ.js.map} +0 -0
- /package/dist/{chunk-HRW7BIDE.js.map → chunk-WS6OQIEN.js.map} +0 -0
- /package/dist/{chunk-TNFACSWF.js.map → chunk-ZLHGJSRK.js.map} +0 -0
- /package/dist/{source-manager-FEGVYDFZ.js.map → source-manager-PPABS6BC.js.map} +0 -0
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
createMockCategory,
|
|
14
14
|
createMockMatrix,
|
|
15
15
|
createMockSkill
|
|
16
|
-
} from "../../chunk-
|
|
16
|
+
} from "../../chunk-AH7XHAKN.js";
|
|
17
17
|
import {
|
|
18
18
|
afterEach,
|
|
19
19
|
describe,
|
|
@@ -23,20 +23,21 @@ import {
|
|
|
23
23
|
} from "../../chunk-XY3XDVMI.js";
|
|
24
24
|
import {
|
|
25
25
|
StepBuild
|
|
26
|
-
} from "../../chunk-
|
|
26
|
+
} from "../../chunk-7FBM7V3E.js";
|
|
27
|
+
import "../../chunk-YRVTXSXP.js";
|
|
28
|
+
import "../../chunk-KXM7KOPE.js";
|
|
27
29
|
import "../../chunk-K77I4XGL.js";
|
|
28
|
-
import "../../chunk-
|
|
29
|
-
import "../../chunk-2XX4TMCI.js";
|
|
30
|
-
import "../../chunk-TA6IIQI4.js";
|
|
30
|
+
import "../../chunk-GEDWVX6Y.js";
|
|
31
31
|
import "../../chunk-GG4BSB6S.js";
|
|
32
|
+
import "../../chunk-423MJ6DT.js";
|
|
32
33
|
import {
|
|
33
34
|
getSkillDisplayLabel,
|
|
34
35
|
validateBuildStep
|
|
35
|
-
} from "../../chunk-
|
|
36
|
-
import "../../chunk-
|
|
36
|
+
} from "../../chunk-SILUTTV7.js";
|
|
37
|
+
import "../../chunk-TTXV55NQ.js";
|
|
37
38
|
import "../../chunk-T4EXUIBY.js";
|
|
38
|
-
import "../../chunk-
|
|
39
|
-
import "../../chunk-
|
|
39
|
+
import "../../chunk-XJXJZ2MJ.js";
|
|
40
|
+
import "../../chunk-BK7TANUV.js";
|
|
40
41
|
import {
|
|
41
42
|
init_esm_shims
|
|
42
43
|
} from "../../chunk-DHET7RCE.js";
|
|
@@ -57,60 +58,60 @@ var buildTestMatrix = (categories, skills) => {
|
|
|
57
58
|
}
|
|
58
59
|
);
|
|
59
60
|
};
|
|
60
|
-
var frameworkCategory = createMockCategory("framework", "Framework", {
|
|
61
|
+
var frameworkCategory = createMockCategory("web-framework", "Framework", {
|
|
61
62
|
domain: "web",
|
|
62
63
|
required: true,
|
|
63
64
|
order: 0
|
|
64
65
|
});
|
|
65
|
-
var stylingCategory = createMockCategory("styling", "Styling", {
|
|
66
|
+
var stylingCategory = createMockCategory("web-styling", "Styling", {
|
|
66
67
|
domain: "web",
|
|
67
68
|
required: true,
|
|
68
69
|
order: 1
|
|
69
70
|
});
|
|
70
|
-
var stateCategory = createMockCategory("client-state", "Client State", {
|
|
71
|
+
var stateCategory = createMockCategory("web-client-state", "Client State", {
|
|
71
72
|
domain: "web",
|
|
72
73
|
required: false,
|
|
73
74
|
order: 2
|
|
74
75
|
});
|
|
75
|
-
var apiFrameworkCategory = createMockCategory("api", "API Framework", {
|
|
76
|
+
var apiFrameworkCategory = createMockCategory("api-api", "API Framework", {
|
|
76
77
|
domain: "api",
|
|
77
78
|
required: true,
|
|
78
79
|
order: 0
|
|
79
80
|
});
|
|
80
|
-
var databaseCategory = createMockCategory("database", "Database", {
|
|
81
|
+
var databaseCategory = createMockCategory("api-database", "Database", {
|
|
81
82
|
domain: "api",
|
|
82
83
|
required: false,
|
|
83
84
|
order: 1
|
|
84
85
|
});
|
|
85
|
-
var reactSkill = createMockSkill("web-framework-react", "framework", {
|
|
86
|
+
var reactSkill = createMockSkill("web-framework-react", "web-framework", {
|
|
86
87
|
...SKILL_DEFAULTS,
|
|
87
88
|
displayName: "react"
|
|
88
89
|
});
|
|
89
|
-
var vueSkill = createMockSkill("web-framework-vue", "framework", {
|
|
90
|
+
var vueSkill = createMockSkill("web-framework-vue", "web-framework", {
|
|
90
91
|
...SKILL_DEFAULTS,
|
|
91
92
|
displayName: "vue"
|
|
92
93
|
});
|
|
93
|
-
var tailwindSkill = createMockSkill("web-styling-tailwind", "styling", {
|
|
94
|
+
var tailwindSkill = createMockSkill("web-styling-tailwind", "web-styling", {
|
|
94
95
|
...SKILL_DEFAULTS,
|
|
95
96
|
displayName: "tailwind"
|
|
96
97
|
});
|
|
97
|
-
var scssSkill = createMockSkill("web-styling-scss-modules", "styling", {
|
|
98
|
+
var scssSkill = createMockSkill("web-styling-scss-modules", "web-styling", {
|
|
98
99
|
...SKILL_DEFAULTS,
|
|
99
100
|
displayName: "scss-modules"
|
|
100
101
|
});
|
|
101
|
-
var zustandSkill = createMockSkill("web-state-zustand", "client-state", {
|
|
102
|
+
var zustandSkill = createMockSkill("web-state-zustand", "web-client-state", {
|
|
102
103
|
...SKILL_DEFAULTS,
|
|
103
104
|
displayName: "zustand"
|
|
104
105
|
});
|
|
105
|
-
var honoSkill = createMockSkill("api-framework-hono", "api", {
|
|
106
|
+
var honoSkill = createMockSkill("api-framework-hono", "api-api", {
|
|
106
107
|
...SKILL_DEFAULTS,
|
|
107
108
|
displayName: "hono"
|
|
108
109
|
});
|
|
109
|
-
var expressSkill = createMockSkill("api-framework-express", "api", {
|
|
110
|
+
var expressSkill = createMockSkill("api-framework-express", "api-api", {
|
|
110
111
|
...SKILL_DEFAULTS,
|
|
111
112
|
displayName: "express"
|
|
112
113
|
});
|
|
113
|
-
var postgresSkill = createMockSkill("api-database-postgres", "database", {
|
|
114
|
+
var postgresSkill = createMockSkill("api-database-postgres", "api-database", {
|
|
114
115
|
...SKILL_DEFAULTS
|
|
115
116
|
});
|
|
116
117
|
var defaultMatrix = buildTestMatrix(
|
|
@@ -151,7 +152,7 @@ describe("StepBuild component", () => {
|
|
|
151
152
|
describe("rendering", () => {
|
|
152
153
|
it("should render CategoryGrid with correct categories for domain", () => {
|
|
153
154
|
const { lastFrame, unmount } = renderStepBuild({
|
|
154
|
-
selections: { framework: ["web-framework-react"] }
|
|
155
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
155
156
|
// Framework selected to show other categories
|
|
156
157
|
});
|
|
157
158
|
cleanup = unmount;
|
|
@@ -175,7 +176,7 @@ describe("StepBuild component", () => {
|
|
|
175
176
|
});
|
|
176
177
|
it("should render skills as options", () => {
|
|
177
178
|
const { lastFrame, unmount } = renderStepBuild({
|
|
178
|
-
selections: { framework: ["web-framework-react"] }
|
|
179
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
179
180
|
});
|
|
180
181
|
cleanup = unmount;
|
|
181
182
|
const output = lastFrame();
|
|
@@ -192,7 +193,7 @@ describe("StepBuild component", () => {
|
|
|
192
193
|
});
|
|
193
194
|
it("should render categories for the domain", () => {
|
|
194
195
|
const { lastFrame, unmount } = renderStepBuild({
|
|
195
|
-
selections: { framework: ["web-framework-react"] }
|
|
196
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
196
197
|
});
|
|
197
198
|
cleanup = unmount;
|
|
198
199
|
const output = lastFrame();
|
|
@@ -240,7 +241,7 @@ describe("StepBuild component", () => {
|
|
|
240
241
|
it("should filter categories correctly by domain", () => {
|
|
241
242
|
const { lastFrame: webFrame, unmount: webUnmount } = renderStepBuild({
|
|
242
243
|
domain: "web",
|
|
243
|
-
selections: { framework: ["web-framework-react"] }
|
|
244
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
244
245
|
});
|
|
245
246
|
const webOutput = webFrame();
|
|
246
247
|
webUnmount();
|
|
@@ -259,7 +260,7 @@ describe("StepBuild component", () => {
|
|
|
259
260
|
});
|
|
260
261
|
it("should sort categories by order", () => {
|
|
261
262
|
const { lastFrame, unmount } = renderStepBuild({
|
|
262
|
-
selections: { framework: ["web-framework-react"] }
|
|
263
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
263
264
|
});
|
|
264
265
|
cleanup = unmount;
|
|
265
266
|
const output = lastFrame();
|
|
@@ -274,7 +275,7 @@ describe("StepBuild component", () => {
|
|
|
274
275
|
it("should show selected options correctly", () => {
|
|
275
276
|
const { lastFrame, unmount } = renderStepBuild({
|
|
276
277
|
allSelections: ["web-framework-react"],
|
|
277
|
-
selections: { framework: ["web-framework-react"] }
|
|
278
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
278
279
|
});
|
|
279
280
|
cleanup = unmount;
|
|
280
281
|
const output = lastFrame();
|
|
@@ -303,8 +304,8 @@ describe("StepBuild component", () => {
|
|
|
303
304
|
const { stdin, unmount } = renderStepBuild({
|
|
304
305
|
onContinue,
|
|
305
306
|
selections: {
|
|
306
|
-
framework: ["web-framework-react"],
|
|
307
|
-
styling: ["web-styling-tailwind"]
|
|
307
|
+
"web-framework": ["web-framework-react"],
|
|
308
|
+
"web-styling": ["web-styling-tailwind"]
|
|
308
309
|
}
|
|
309
310
|
});
|
|
310
311
|
cleanup = unmount;
|
|
@@ -382,7 +383,7 @@ describe("StepBuild component", () => {
|
|
|
382
383
|
domain: "web",
|
|
383
384
|
allSelections: ["api-framework-hono", "api-database-drizzle"],
|
|
384
385
|
// API skills (aliases)
|
|
385
|
-
selections: { framework: ["web-framework-react"] }
|
|
386
|
+
selections: { "web-framework": ["web-framework-react"] }
|
|
386
387
|
// Need framework to see other categories
|
|
387
388
|
});
|
|
388
389
|
cleanup = unmount;
|
|
@@ -482,14 +483,14 @@ describe("StepBuild component", () => {
|
|
|
482
483
|
it("should return valid when required categories have selections", () => {
|
|
483
484
|
const categories = [
|
|
484
485
|
{
|
|
485
|
-
id: "framework",
|
|
486
|
+
id: "web-framework",
|
|
486
487
|
displayName: "Framework",
|
|
487
488
|
required: true,
|
|
488
489
|
exclusive: true,
|
|
489
490
|
options: [{ id: "web-framework-react", label: "React", state: "normal", selected: true }]
|
|
490
491
|
}
|
|
491
492
|
];
|
|
492
|
-
const selections = { framework: ["web-framework-react"] };
|
|
493
|
+
const selections = { "web-framework": ["web-framework-react"] };
|
|
493
494
|
const result = validateBuildStep(categories, selections);
|
|
494
495
|
globalExpect(result.valid).toBe(true);
|
|
495
496
|
globalExpect(result.message).toBeUndefined();
|
|
@@ -497,7 +498,7 @@ describe("StepBuild component", () => {
|
|
|
497
498
|
it("should return invalid when required category has no selection", () => {
|
|
498
499
|
const categories = [
|
|
499
500
|
{
|
|
500
|
-
id: "framework",
|
|
501
|
+
id: "web-framework",
|
|
501
502
|
displayName: "Framework",
|
|
502
503
|
required: true,
|
|
503
504
|
exclusive: true,
|
|
@@ -514,7 +515,7 @@ describe("StepBuild component", () => {
|
|
|
514
515
|
it("should return valid when optional categories have no selections", () => {
|
|
515
516
|
const categories = [
|
|
516
517
|
{
|
|
517
|
-
id: "client-state",
|
|
518
|
+
id: "web-client-state",
|
|
518
519
|
displayName: "State Management",
|
|
519
520
|
required: false,
|
|
520
521
|
exclusive: true,
|
|
@@ -535,14 +536,14 @@ describe("StepBuild component", () => {
|
|
|
535
536
|
it("should return invalid for first missing required category", () => {
|
|
536
537
|
const categories = [
|
|
537
538
|
{
|
|
538
|
-
id: "framework",
|
|
539
|
+
id: "web-framework",
|
|
539
540
|
displayName: "Framework",
|
|
540
541
|
required: true,
|
|
541
542
|
exclusive: true,
|
|
542
543
|
options: []
|
|
543
544
|
},
|
|
544
545
|
{
|
|
545
|
-
id: "styling",
|
|
546
|
+
id: "web-styling",
|
|
546
547
|
displayName: "Styling",
|
|
547
548
|
required: true,
|
|
548
549
|
exclusive: true,
|
|
@@ -575,8 +576,8 @@ describe("StepBuild component", () => {
|
|
|
575
576
|
const { stdin, unmount } = renderStepBuild({
|
|
576
577
|
onContinue,
|
|
577
578
|
selections: {
|
|
578
|
-
framework: ["web-framework-react"],
|
|
579
|
-
styling: ["web-styling-tailwind"]
|
|
579
|
+
"web-framework": ["web-framework-react"],
|
|
580
|
+
"web-styling": ["web-styling-tailwind"]
|
|
580
581
|
}
|
|
581
582
|
});
|
|
582
583
|
cleanup = unmount;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/components/wizard/step-build.test.tsx"],"sourcesContent":["import { render } from \"ink-testing-library\";\nimport { indexBy, mapToObj } from \"remeda\";\nimport { describe, expect, it, afterEach, vi } from \"vitest\";\nimport { StepBuild, type StepBuildProps } from \"./step-build\";\nimport { validateBuildStep, getSkillDisplayLabel } from \"../../lib/wizard/index\";\nimport type { CategoryRow as GridCategoryRow } from \"./category-grid\";\nimport type {\n CategoryDefinition,\n ResolvedSkill,\n SkillDisplayName,\n SkillId,\n Subcategory,\n SubcategorySelections,\n} from \"../../types\";\nimport {\n ENTER,\n ESCAPE,\n RENDER_DELAY_MS,\n INPUT_DELAY_MS,\n delay,\n} from \"../../lib/__tests__/test-constants\";\nimport { createMockCategory, createMockSkill, createMockMatrix } from \"../../lib/__tests__/helpers\";\n\nconst SKILL_DEFAULTS: Partial<ResolvedSkill> = { categoryExclusive: true };\n\n// Test data construction casts: indexBy/mapToObj return generic Records\nconst buildTestMatrix = (categories: CategoryDefinition[], skills: ResolvedSkill[]) => {\n const withDisplayName = skills.filter((s) => s.displayName);\n return createMockMatrix(\n indexBy(skills, (s) => s.id),\n {\n categories: indexBy(categories, (c) => c.id) as Record<Subcategory, CategoryDefinition>,\n displayNameToId: mapToObj(withDisplayName, (s) => [s.displayName!, s.id]) as Record<\n SkillDisplayName,\n SkillId\n >,\n displayNames: mapToObj(withDisplayName, (s) => [s.id, s.displayName!]) as Record<\n SkillId,\n SkillDisplayName\n >,\n },\n );\n};\n\nconst frameworkCategory = createMockCategory(\"framework\", \"Framework\", {\n domain: \"web\",\n required: true,\n order: 0,\n});\n\nconst stylingCategory = createMockCategory(\"styling\", \"Styling\", {\n domain: \"web\",\n required: true,\n order: 1,\n});\n\nconst stateCategory = createMockCategory(\"client-state\", \"Client State\", {\n domain: \"web\",\n required: false,\n order: 2,\n});\n\nconst apiFrameworkCategory = createMockCategory(\"api\", \"API Framework\", {\n domain: \"api\",\n required: true,\n order: 0,\n});\n\nconst databaseCategory = createMockCategory(\"database\", \"Database\", {\n domain: \"api\",\n required: false,\n order: 1,\n});\n\nconst reactSkill = createMockSkill(\"web-framework-react\", \"framework\", {\n ...SKILL_DEFAULTS,\n displayName: \"react\",\n});\n\nconst vueSkill = createMockSkill(\"web-framework-vue\", \"framework\", {\n ...SKILL_DEFAULTS,\n displayName: \"vue\",\n});\n\nconst tailwindSkill = createMockSkill(\"web-styling-tailwind\", \"styling\", {\n ...SKILL_DEFAULTS,\n displayName: \"tailwind\",\n});\n\nconst scssSkill = createMockSkill(\"web-styling-scss-modules\", \"styling\", {\n ...SKILL_DEFAULTS,\n displayName: \"scss-modules\",\n});\n\nconst zustandSkill = createMockSkill(\"web-state-zustand\", \"client-state\", {\n ...SKILL_DEFAULTS,\n displayName: \"zustand\",\n});\n\nconst honoSkill = createMockSkill(\"api-framework-hono\", \"api\", {\n ...SKILL_DEFAULTS,\n displayName: \"hono\",\n});\n\nconst expressSkill = createMockSkill(\"api-framework-express\", \"api\", {\n ...SKILL_DEFAULTS,\n displayName: \"express\",\n});\n\nconst postgresSkill = createMockSkill(\"api-database-postgres\", \"database\", {\n ...SKILL_DEFAULTS,\n});\n\nconst defaultMatrix = buildTestMatrix(\n [frameworkCategory, stylingCategory, stateCategory, apiFrameworkCategory, databaseCategory],\n [\n reactSkill,\n vueSkill,\n tailwindSkill,\n scssSkill,\n zustandSkill,\n honoSkill,\n expressSkill,\n postgresSkill,\n ],\n);\n\nconst defaultProps: StepBuildProps = {\n matrix: defaultMatrix,\n domain: \"web\",\n selectedDomains: [\"web\"],\n selections: {},\n allSelections: [],\n showLabels: false,\n expertMode: false,\n onToggle: vi.fn(),\n onToggleLabels: vi.fn(),\n onContinue: vi.fn(),\n onBack: vi.fn(),\n};\n\nconst renderStepBuild = (props: Partial<StepBuildProps> = {}) => {\n return render(<StepBuild {...defaultProps} {...props} />);\n};\n\ndescribe(\"StepBuild component\", () => {\n let cleanup: (() => void) | undefined;\n\n afterEach(() => {\n cleanup?.();\n cleanup = undefined;\n });\n\n describe(\"rendering\", () => {\n it(\"should render CategoryGrid with correct categories for domain\", () => {\n // For web domain with framework-first flow, initially only shows Framework\n // To see other categories, need a framework selection\n const { lastFrame, unmount } = renderStepBuild({\n selections: { framework: [\"web-framework-react\"] }, // Framework selected to show other categories\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Web domain should show Framework, Styling, Client State (when framework selected)\n expect(output).toContain(\"Framework\");\n expect(output).toContain(\"Styling\");\n expect(output).toContain(\"Client State\");\n // Should NOT show API categories\n expect(output).not.toContain(\"API Framework\");\n expect(output).not.toContain(\"Database\");\n });\n\n it(\"should render API categories when domain is api\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // API domain should show API Framework, Database\n expect(output).toContain(\"API Framework\");\n expect(output).toContain(\"Database\");\n // Should NOT show Web categories\n expect(output).not.toContain(\"Styling\");\n expect(output).not.toContain(\"Client State\");\n });\n\n it(\"should render skills as options\", () => {\n // Need framework selected to see other categories in web domain\n const { lastFrame, unmount } = renderStepBuild({\n selections: { framework: [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Framework skills (displayed as alias)\n expect(output).toContain(\"react\");\n expect(output).toContain(\"vue\");\n // Styling skills (visible after framework selected)\n expect(output).toContain(\"tailwind\");\n expect(output).toContain(\"scss-modules\");\n });\n\n it(\"should show required indicator (*) for required categories\", () => {\n const { lastFrame, unmount } = renderStepBuild();\n cleanup = unmount;\n\n const output = lastFrame();\n // Framework and Styling are required\n expect(output).toContain(\"*\");\n });\n\n it(\"should render categories for the domain\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selections: { framework: [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should render the domain categories\n expect(output).toContain(\"Framework\");\n expect(output).toContain(\"Styling\");\n });\n });\n\n describe(\"domain header\", () => {\n it(\"should show ViewTitle with current domain when multiple domains selected\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\", \"api\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should show ViewTitle with domain when only one selected\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should show ViewTitle for current domain on final domain\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\", \"api\"],\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n\n it(\"should show correct domain display names\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\", \"api\", \"cli\"],\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n });\n\n describe(\"category filtering\", () => {\n it(\"should filter categories correctly by domain\", () => {\n // Web domain with framework selected (to bypass framework-first filter)\n const { lastFrame: webFrame, unmount: webUnmount } = renderStepBuild({\n domain: \"web\",\n selections: { framework: [\"web-framework-react\"] },\n });\n const webOutput = webFrame();\n webUnmount();\n\n // API domain (no framework-first filter for API)\n const { lastFrame: apiFrame, unmount: apiUnmount } = renderStepBuild({\n domain: \"api\",\n });\n cleanup = apiUnmount;\n const apiOutput = apiFrame();\n\n // Web should have Framework, Styling, Client State (with framework selected)\n expect(webOutput).toContain(\"Framework\");\n expect(webOutput).toContain(\"Styling\");\n expect(webOutput).toContain(\"Client State\");\n expect(webOutput).not.toContain(\"API Framework\");\n\n // API should have API Framework, Database\n expect(apiOutput).toContain(\"API Framework\");\n expect(apiOutput).toContain(\"Database\");\n expect(apiOutput).not.toContain(\"Styling\");\n });\n\n it(\"should sort categories by order\", () => {\n // Need framework selected to see all categories\n const { lastFrame, unmount } = renderStepBuild({\n selections: { framework: [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Framework (order 0) should appear before Styling (order 1)\n // and Styling before Client State (order 2)\n const frameworkIndex = output?.indexOf(\"Framework\") ?? -1;\n const stylingIndex = output?.indexOf(\"Styling\") ?? -1;\n const stateIndex = output?.indexOf(\"Client State\") ?? -1;\n\n expect(frameworkIndex).toBeLessThan(stylingIndex);\n expect(stylingIndex).toBeLessThan(stateIndex);\n });\n });\n\n describe(\"option states\", () => {\n it(\"should show selected options correctly\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n allSelections: [\"web-framework-react\"],\n selections: { framework: [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should show selected option (no circle symbol anymore, uses background)\n // Just verify the selected label is present (displayed as alias)\n expect(output).toContain(\"react\");\n });\n\n it(\"should pass expertMode to CategoryGrid\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n expertMode: true,\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Expert mode is passed to CategoryGrid for option sorting behavior\n // The visual indicator is now shown globally in wizard-layout, not in CategoryGrid header\n expect(output).toBeDefined();\n });\n\n it(\"should pass showLabels to CategoryGrid\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n showLabels: true,\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Labels toggle is now shown globally in wizard-layout\n // Verify component renders without error\n expect(output).toBeDefined();\n });\n });\n\n describe(\"keyboard navigation\", () => {\n it(\"should call onContinue when Enter is pressed with valid selections\", async () => {\n const onContinue = vi.fn();\n // Provide selections for required categories to pass validation\n const { stdin, unmount } = renderStepBuild({\n onContinue,\n selections: {\n framework: [\"web-framework-react\"],\n styling: [\"web-styling-tailwind\"],\n },\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(ENTER);\n await delay(INPUT_DELAY_MS);\n\n expect(onContinue).toHaveBeenCalled();\n });\n\n it(\"should call onBack when Escape is pressed\", async () => {\n const onBack = vi.fn();\n const { stdin, unmount } = renderStepBuild({ onBack });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(ESCAPE);\n await delay(INPUT_DELAY_MS);\n\n expect(onBack).toHaveBeenCalled();\n });\n\n it(\"should pass toggle callback to CategoryGrid\", async () => {\n const onToggle = vi.fn();\n const { stdin, unmount } = renderStepBuild({\n onToggle,\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n // Space should trigger toggle\n stdin.write(\" \");\n await delay(INPUT_DELAY_MS);\n\n expect(onToggle).toHaveBeenCalled();\n });\n });\n\n describe(\"toggle callbacks\", () => {\n it(\"should pass onToggleLabels to CategoryGrid\", async () => {\n const onToggleLabels = vi.fn();\n const { stdin, unmount } = renderStepBuild({ onToggleLabels });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(\"d\"); // 'd' key toggles compatibility labels\n await delay(INPUT_DELAY_MS);\n\n expect(onToggleLabels).toHaveBeenCalled();\n });\n\n it(\"should not handle expert mode toggle locally (handled globally)\", () => {\n // Expert mode toggle is now handled at wizard.tsx level\n // StepBuild no longer has onToggleExpertMode prop\n const { lastFrame, unmount } = renderStepBuild();\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toBeDefined();\n });\n });\n\n describe(\"edge cases\", () => {\n it(\"should handle domain with no categories\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"mobile\", // No mobile categories in test matrix\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should show empty state message from CategoryGrid\n expect(output).toContain(\"No categories to display\");\n });\n\n it(\"should handle unknown domain gracefully\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"shared\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should render without crashing\n expect(output).toBeDefined();\n });\n\n it(\"should handle empty allSelections\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n allSelections: [],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Framework\");\n });\n\n it(\"should handle allSelections with skills from other domains\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"web\",\n allSelections: [\"api-framework-hono\", \"api-database-drizzle\"], // API skills (aliases)\n selections: { framework: [\"web-framework-react\"] }, // Need framework to see other categories\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should still render web categories\n expect(output).toContain(\"Framework\");\n expect(output).toContain(\"Styling\");\n });\n });\n\n describe(\"multi-domain scenarios\", () => {\n it(\"should show ViewTitle for current domain in multi-domain flow\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"web\",\n selectedDomains: [\"web\", \"api\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should show ViewTitle for last domain in multi-domain flow\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"api\",\n selectedDomains: [\"web\", \"api\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n\n it(\"should show ViewTitle for current domain in three-domain flow\", () => {\n // Add cli category to matrix\n const cliFrameworkCategory = createMockCategory(\"cli-framework\", \"CLI Framework\", {\n domain: \"cli\",\n required: true,\n order: 0,\n });\n const commanderSkill = createMockSkill(\"cli-cli-framework-commander\", \"cli-framework\", {\n ...SKILL_DEFAULTS,\n displayName: \"commander\",\n });\n\n const matrixWithCli = buildTestMatrix(\n [\n frameworkCategory,\n stylingCategory,\n stateCategory,\n apiFrameworkCategory,\n databaseCategory,\n cliFrameworkCategory,\n ],\n [\n reactSkill,\n vueSkill,\n tailwindSkill,\n scssSkill,\n zustandSkill,\n honoSkill,\n expressSkill,\n postgresSkill,\n commanderSkill,\n ],\n );\n\n const { lastFrame, unmount } = renderStepBuild({\n matrix: matrixWithCli,\n domain: \"api\",\n selectedDomains: [\"web\", \"api\", \"cli\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n });\n\n describe(\"header and selection count\", () => {\n it(\"should show ViewTitle with domain name\", () => {\n const { lastFrame, unmount } = renderStepBuild();\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should render ViewTitle with domain display name\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n });\n\n describe(\"keyboard help text\", () => {\n it(\"should respond to d key for toggling compatibility labels\", async () => {\n const onToggleLabels = vi.fn();\n const { stdin, unmount } = renderStepBuild({ onToggleLabels });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(\"d\");\n await delay(INPUT_DELAY_MS);\n\n expect(onToggleLabels).toHaveBeenCalled();\n });\n });\n\n describe(\"validateBuildStep\", () => {\n it(\"should return valid when required categories have selections\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"framework\",\n displayName: \"Framework\",\n required: true,\n exclusive: true,\n options: [{ id: \"web-framework-react\", label: \"React\", state: \"normal\", selected: true }],\n },\n ];\n const selections: SubcategorySelections = { framework: [\"web-framework-react\"] };\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(true);\n expect(result.message).toBeUndefined();\n });\n\n it(\"should return invalid when required category has no selection\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"framework\",\n displayName: \"Framework\",\n required: true,\n exclusive: true,\n options: [\n { id: \"web-framework-react\", label: \"React\", state: \"normal\", selected: false },\n ],\n },\n ];\n const selections: SubcategorySelections = {};\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(false);\n expect(result.message).toContain(\"Framework\");\n });\n\n it(\"should return valid when optional categories have no selections\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"client-state\",\n displayName: \"State Management\",\n required: false,\n exclusive: true,\n options: [\n {\n id: \"web-state-zustand\",\n label: \"Zustand\",\n state: \"normal\",\n selected: false,\n },\n ],\n },\n ];\n const selections: SubcategorySelections = {};\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(true);\n });\n\n it(\"should return invalid for first missing required category\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"framework\",\n displayName: \"Framework\",\n required: true,\n exclusive: true,\n options: [],\n },\n {\n id: \"styling\",\n displayName: \"Styling\",\n required: true,\n exclusive: true,\n options: [],\n },\n ];\n const selections: SubcategorySelections = {};\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(false);\n expect(result.message).toContain(\"Framework\"); // Should be the first one\n });\n });\n\n describe(\"validation on continue\", () => {\n it(\"should show validation error when trying to continue without required selection\", async () => {\n const onContinue = vi.fn();\n const { stdin, lastFrame, unmount } = renderStepBuild({\n onContinue,\n selections: {},\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n\n // Press Enter to continue without selecting required framework\n stdin.write(ENTER);\n await delay(INPUT_DELAY_MS);\n\n // Should show validation error and NOT call onContinue\n const output = lastFrame();\n expect(output).toContain(\"Select at least one skill\");\n expect(onContinue).not.toHaveBeenCalled();\n });\n\n it(\"should call onContinue when validation passes\", async () => {\n const onContinue = vi.fn();\n const { stdin, unmount } = renderStepBuild({\n onContinue,\n selections: {\n framework: [\"web-framework-react\"],\n styling: [\"web-styling-tailwind\"],\n },\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n\n // Press Enter to continue with required selections\n stdin.write(ENTER);\n await delay(INPUT_DELAY_MS);\n\n expect(onContinue).toHaveBeenCalled();\n });\n });\n});\n\ndescribe(\"getSkillDisplayLabel\", () => {\n it(\"should return displayName when available\", () => {\n expect(getSkillDisplayLabel({ displayName: \"react\", id: \"web-framework-react\" })).toBe(\"react\");\n });\n\n it(\"should return id when no displayName\", () => {\n expect(getSkillDisplayLabel({ id: \"web-framework-react\" })).toBe(\"web-framework-react\");\n });\n\n it(\"should prefer displayName over id\", () => {\n expect(\n getSkillDisplayLabel({ displayName: \"scss-modules\", id: \"web-styling-scss-modules\" }),\n ).toBe(\"scss-modules\");\n });\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/components/wizard/step-build.test.tsx"],"sourcesContent":["import { render } from \"ink-testing-library\";\nimport { indexBy, mapToObj } from \"remeda\";\nimport { describe, expect, it, afterEach, vi } from \"vitest\";\nimport { StepBuild, type StepBuildProps } from \"./step-build\";\nimport { validateBuildStep, getSkillDisplayLabel } from \"../../lib/wizard/index\";\nimport type { CategoryRow as GridCategoryRow } from \"./category-grid\";\nimport type {\n CategoryDefinition,\n ResolvedSkill,\n SkillDisplayName,\n SkillId,\n Subcategory,\n SubcategorySelections,\n} from \"../../types\";\nimport {\n ENTER,\n ESCAPE,\n RENDER_DELAY_MS,\n INPUT_DELAY_MS,\n delay,\n} from \"../../lib/__tests__/test-constants\";\nimport { createMockCategory, createMockSkill, createMockMatrix } from \"../../lib/__tests__/helpers\";\n\nconst SKILL_DEFAULTS: Partial<ResolvedSkill> = { categoryExclusive: true };\n\n// Test data construction casts: indexBy/mapToObj return generic Records\nconst buildTestMatrix = (categories: CategoryDefinition[], skills: ResolvedSkill[]) => {\n const withDisplayName = skills.filter((s) => s.displayName);\n return createMockMatrix(\n indexBy(skills, (s) => s.id),\n {\n categories: indexBy(categories, (c) => c.id) as Record<Subcategory, CategoryDefinition>,\n displayNameToId: mapToObj(withDisplayName, (s) => [s.displayName!, s.id]) as Record<\n SkillDisplayName,\n SkillId\n >,\n displayNames: mapToObj(withDisplayName, (s) => [s.id, s.displayName!]) as Record<\n SkillId,\n SkillDisplayName\n >,\n },\n );\n};\n\nconst frameworkCategory = createMockCategory(\"web-framework\", \"Framework\", {\n domain: \"web\",\n required: true,\n order: 0,\n});\n\nconst stylingCategory = createMockCategory(\"web-styling\", \"Styling\", {\n domain: \"web\",\n required: true,\n order: 1,\n});\n\nconst stateCategory = createMockCategory(\"web-client-state\", \"Client State\", {\n domain: \"web\",\n required: false,\n order: 2,\n});\n\nconst apiFrameworkCategory = createMockCategory(\"api-api\", \"API Framework\", {\n domain: \"api\",\n required: true,\n order: 0,\n});\n\nconst databaseCategory = createMockCategory(\"api-database\", \"Database\", {\n domain: \"api\",\n required: false,\n order: 1,\n});\n\nconst reactSkill = createMockSkill(\"web-framework-react\", \"web-framework\", {\n ...SKILL_DEFAULTS,\n displayName: \"react\",\n});\n\nconst vueSkill = createMockSkill(\"web-framework-vue\", \"web-framework\", {\n ...SKILL_DEFAULTS,\n displayName: \"vue\",\n});\n\nconst tailwindSkill = createMockSkill(\"web-styling-tailwind\", \"web-styling\", {\n ...SKILL_DEFAULTS,\n displayName: \"tailwind\",\n});\n\nconst scssSkill = createMockSkill(\"web-styling-scss-modules\", \"web-styling\", {\n ...SKILL_DEFAULTS,\n displayName: \"scss-modules\",\n});\n\nconst zustandSkill = createMockSkill(\"web-state-zustand\", \"web-client-state\", {\n ...SKILL_DEFAULTS,\n displayName: \"zustand\",\n});\n\nconst honoSkill = createMockSkill(\"api-framework-hono\", \"api-api\", {\n ...SKILL_DEFAULTS,\n displayName: \"hono\",\n});\n\nconst expressSkill = createMockSkill(\"api-framework-express\", \"api-api\", {\n ...SKILL_DEFAULTS,\n displayName: \"express\",\n});\n\nconst postgresSkill = createMockSkill(\"api-database-postgres\", \"api-database\", {\n ...SKILL_DEFAULTS,\n});\n\nconst defaultMatrix = buildTestMatrix(\n [frameworkCategory, stylingCategory, stateCategory, apiFrameworkCategory, databaseCategory],\n [\n reactSkill,\n vueSkill,\n tailwindSkill,\n scssSkill,\n zustandSkill,\n honoSkill,\n expressSkill,\n postgresSkill,\n ],\n);\n\nconst defaultProps: StepBuildProps = {\n matrix: defaultMatrix,\n domain: \"web\",\n selectedDomains: [\"web\"],\n selections: {},\n allSelections: [],\n showLabels: false,\n expertMode: false,\n onToggle: vi.fn(),\n onToggleLabels: vi.fn(),\n onContinue: vi.fn(),\n onBack: vi.fn(),\n};\n\nconst renderStepBuild = (props: Partial<StepBuildProps> = {}) => {\n return render(<StepBuild {...defaultProps} {...props} />);\n};\n\ndescribe(\"StepBuild component\", () => {\n let cleanup: (() => void) | undefined;\n\n afterEach(() => {\n cleanup?.();\n cleanup = undefined;\n });\n\n describe(\"rendering\", () => {\n it(\"should render CategoryGrid with correct categories for domain\", () => {\n // For web domain with framework-first flow, initially only shows Framework\n // To see other categories, need a framework selection\n const { lastFrame, unmount } = renderStepBuild({\n selections: { \"web-framework\": [\"web-framework-react\"] }, // Framework selected to show other categories\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Web domain should show Framework, Styling, Client State (when framework selected)\n expect(output).toContain(\"Framework\");\n expect(output).toContain(\"Styling\");\n expect(output).toContain(\"Client State\");\n // Should NOT show API categories\n expect(output).not.toContain(\"API Framework\");\n expect(output).not.toContain(\"Database\");\n });\n\n it(\"should render API categories when domain is api\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // API domain should show API Framework, Database\n expect(output).toContain(\"API Framework\");\n expect(output).toContain(\"Database\");\n // Should NOT show Web categories\n expect(output).not.toContain(\"Styling\");\n expect(output).not.toContain(\"Client State\");\n });\n\n it(\"should render skills as options\", () => {\n // Need framework selected to see other categories in web domain\n const { lastFrame, unmount } = renderStepBuild({\n selections: { \"web-framework\": [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Framework skills (displayed as alias)\n expect(output).toContain(\"react\");\n expect(output).toContain(\"vue\");\n // Styling skills (visible after framework selected)\n expect(output).toContain(\"tailwind\");\n expect(output).toContain(\"scss-modules\");\n });\n\n it(\"should show required indicator (*) for required categories\", () => {\n const { lastFrame, unmount } = renderStepBuild();\n cleanup = unmount;\n\n const output = lastFrame();\n // Framework and Styling are required\n expect(output).toContain(\"*\");\n });\n\n it(\"should render categories for the domain\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selections: { \"web-framework\": [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should render the domain categories\n expect(output).toContain(\"Framework\");\n expect(output).toContain(\"Styling\");\n });\n });\n\n describe(\"domain header\", () => {\n it(\"should show ViewTitle with current domain when multiple domains selected\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\", \"api\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should show ViewTitle with domain when only one selected\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should show ViewTitle for current domain on final domain\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\", \"api\"],\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n\n it(\"should show correct domain display names\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n selectedDomains: [\"web\", \"api\", \"cli\"],\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n });\n\n describe(\"category filtering\", () => {\n it(\"should filter categories correctly by domain\", () => {\n // Web domain with framework selected (to bypass framework-first filter)\n const { lastFrame: webFrame, unmount: webUnmount } = renderStepBuild({\n domain: \"web\",\n selections: { \"web-framework\": [\"web-framework-react\"] },\n });\n const webOutput = webFrame();\n webUnmount();\n\n // API domain (no framework-first filter for API)\n const { lastFrame: apiFrame, unmount: apiUnmount } = renderStepBuild({\n domain: \"api\",\n });\n cleanup = apiUnmount;\n const apiOutput = apiFrame();\n\n // Web should have Framework, Styling, Client State (with framework selected)\n expect(webOutput).toContain(\"Framework\");\n expect(webOutput).toContain(\"Styling\");\n expect(webOutput).toContain(\"Client State\");\n expect(webOutput).not.toContain(\"API Framework\");\n\n // API should have API Framework, Database\n expect(apiOutput).toContain(\"API Framework\");\n expect(apiOutput).toContain(\"Database\");\n expect(apiOutput).not.toContain(\"Styling\");\n });\n\n it(\"should sort categories by order\", () => {\n // Need framework selected to see all categories\n const { lastFrame, unmount } = renderStepBuild({\n selections: { \"web-framework\": [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Framework (order 0) should appear before Styling (order 1)\n // and Styling before Client State (order 2)\n const frameworkIndex = output?.indexOf(\"Framework\") ?? -1;\n const stylingIndex = output?.indexOf(\"Styling\") ?? -1;\n const stateIndex = output?.indexOf(\"Client State\") ?? -1;\n\n expect(frameworkIndex).toBeLessThan(stylingIndex);\n expect(stylingIndex).toBeLessThan(stateIndex);\n });\n });\n\n describe(\"option states\", () => {\n it(\"should show selected options correctly\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n allSelections: [\"web-framework-react\"],\n selections: { \"web-framework\": [\"web-framework-react\"] },\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should show selected option (no circle symbol anymore, uses background)\n // Just verify the selected label is present (displayed as alias)\n expect(output).toContain(\"react\");\n });\n\n it(\"should pass expertMode to CategoryGrid\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n expertMode: true,\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Expert mode is passed to CategoryGrid for option sorting behavior\n // The visual indicator is now shown globally in wizard-layout, not in CategoryGrid header\n expect(output).toBeDefined();\n });\n\n it(\"should pass showLabels to CategoryGrid\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n showLabels: true,\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Labels toggle is now shown globally in wizard-layout\n // Verify component renders without error\n expect(output).toBeDefined();\n });\n });\n\n describe(\"keyboard navigation\", () => {\n it(\"should call onContinue when Enter is pressed with valid selections\", async () => {\n const onContinue = vi.fn();\n // Provide selections for required categories to pass validation\n const { stdin, unmount } = renderStepBuild({\n onContinue,\n selections: {\n \"web-framework\": [\"web-framework-react\"],\n \"web-styling\": [\"web-styling-tailwind\"],\n },\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(ENTER);\n await delay(INPUT_DELAY_MS);\n\n expect(onContinue).toHaveBeenCalled();\n });\n\n it(\"should call onBack when Escape is pressed\", async () => {\n const onBack = vi.fn();\n const { stdin, unmount } = renderStepBuild({ onBack });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(ESCAPE);\n await delay(INPUT_DELAY_MS);\n\n expect(onBack).toHaveBeenCalled();\n });\n\n it(\"should pass toggle callback to CategoryGrid\", async () => {\n const onToggle = vi.fn();\n const { stdin, unmount } = renderStepBuild({\n onToggle,\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n // Space should trigger toggle\n stdin.write(\" \");\n await delay(INPUT_DELAY_MS);\n\n expect(onToggle).toHaveBeenCalled();\n });\n });\n\n describe(\"toggle callbacks\", () => {\n it(\"should pass onToggleLabels to CategoryGrid\", async () => {\n const onToggleLabels = vi.fn();\n const { stdin, unmount } = renderStepBuild({ onToggleLabels });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(\"d\"); // 'd' key toggles compatibility labels\n await delay(INPUT_DELAY_MS);\n\n expect(onToggleLabels).toHaveBeenCalled();\n });\n\n it(\"should not handle expert mode toggle locally (handled globally)\", () => {\n // Expert mode toggle is now handled at wizard.tsx level\n // StepBuild no longer has onToggleExpertMode prop\n const { lastFrame, unmount } = renderStepBuild();\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toBeDefined();\n });\n });\n\n describe(\"edge cases\", () => {\n it(\"should handle domain with no categories\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"mobile\", // No mobile categories in test matrix\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should show empty state message from CategoryGrid\n expect(output).toContain(\"No categories to display\");\n });\n\n it(\"should handle unknown domain gracefully\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"shared\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should render without crashing\n expect(output).toBeDefined();\n });\n\n it(\"should handle empty allSelections\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n allSelections: [],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Framework\");\n });\n\n it(\"should handle allSelections with skills from other domains\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"web\",\n allSelections: [\"api-framework-hono\", \"api-database-drizzle\"], // API skills (aliases)\n selections: { \"web-framework\": [\"web-framework-react\"] }, // Need framework to see other categories\n });\n cleanup = unmount;\n\n const output = lastFrame();\n // Should still render web categories\n expect(output).toContain(\"Framework\");\n expect(output).toContain(\"Styling\");\n });\n });\n\n describe(\"multi-domain scenarios\", () => {\n it(\"should show ViewTitle for current domain in multi-domain flow\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"web\",\n selectedDomains: [\"web\", \"api\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should show ViewTitle for last domain in multi-domain flow\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"api\",\n selectedDomains: [\"web\", \"api\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n\n it(\"should show ViewTitle for current domain in three-domain flow\", () => {\n // Add cli category to matrix\n const cliFrameworkCategory = createMockCategory(\"cli-framework\", \"CLI Framework\", {\n domain: \"cli\",\n required: true,\n order: 0,\n });\n const commanderSkill = createMockSkill(\"cli-cli-framework-commander\", \"cli-framework\", {\n ...SKILL_DEFAULTS,\n displayName: \"commander\",\n });\n\n const matrixWithCli = buildTestMatrix(\n [\n frameworkCategory,\n stylingCategory,\n stateCategory,\n apiFrameworkCategory,\n databaseCategory,\n cliFrameworkCategory,\n ],\n [\n reactSkill,\n vueSkill,\n tailwindSkill,\n scssSkill,\n zustandSkill,\n honoSkill,\n expressSkill,\n postgresSkill,\n commanderSkill,\n ],\n );\n\n const { lastFrame, unmount } = renderStepBuild({\n matrix: matrixWithCli,\n domain: \"api\",\n selectedDomains: [\"web\", \"api\", \"cli\"],\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n });\n\n describe(\"header and selection count\", () => {\n it(\"should show ViewTitle with domain name\", () => {\n const { lastFrame, unmount } = renderStepBuild();\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your Web stack\");\n });\n\n it(\"should render ViewTitle with domain display name\", () => {\n const { lastFrame, unmount } = renderStepBuild({\n domain: \"api\",\n });\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"[2] Customize your API stack\");\n });\n });\n\n describe(\"keyboard help text\", () => {\n it(\"should respond to d key for toggling compatibility labels\", async () => {\n const onToggleLabels = vi.fn();\n const { stdin, unmount } = renderStepBuild({ onToggleLabels });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n stdin.write(\"d\");\n await delay(INPUT_DELAY_MS);\n\n expect(onToggleLabels).toHaveBeenCalled();\n });\n });\n\n describe(\"validateBuildStep\", () => {\n it(\"should return valid when required categories have selections\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"web-framework\",\n displayName: \"Framework\",\n required: true,\n exclusive: true,\n options: [{ id: \"web-framework-react\", label: \"React\", state: \"normal\", selected: true }],\n },\n ];\n const selections: SubcategorySelections = { \"web-framework\": [\"web-framework-react\"] };\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(true);\n expect(result.message).toBeUndefined();\n });\n\n it(\"should return invalid when required category has no selection\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"web-framework\",\n displayName: \"Framework\",\n required: true,\n exclusive: true,\n options: [\n { id: \"web-framework-react\", label: \"React\", state: \"normal\", selected: false },\n ],\n },\n ];\n const selections: SubcategorySelections = {};\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(false);\n expect(result.message).toContain(\"Framework\");\n });\n\n it(\"should return valid when optional categories have no selections\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"web-client-state\",\n displayName: \"State Management\",\n required: false,\n exclusive: true,\n options: [\n {\n id: \"web-state-zustand\",\n label: \"Zustand\",\n state: \"normal\",\n selected: false,\n },\n ],\n },\n ];\n const selections: SubcategorySelections = {};\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(true);\n });\n\n it(\"should return invalid for first missing required category\", () => {\n const categories: GridCategoryRow[] = [\n {\n id: \"web-framework\",\n displayName: \"Framework\",\n required: true,\n exclusive: true,\n options: [],\n },\n {\n id: \"web-styling\",\n displayName: \"Styling\",\n required: true,\n exclusive: true,\n options: [],\n },\n ];\n const selections: SubcategorySelections = {};\n\n const result = validateBuildStep(categories, selections);\n expect(result.valid).toBe(false);\n expect(result.message).toContain(\"Framework\"); // Should be the first one\n });\n });\n\n describe(\"validation on continue\", () => {\n it(\"should show validation error when trying to continue without required selection\", async () => {\n const onContinue = vi.fn();\n const { stdin, lastFrame, unmount } = renderStepBuild({\n onContinue,\n selections: {},\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n\n // Press Enter to continue without selecting required framework\n stdin.write(ENTER);\n await delay(INPUT_DELAY_MS);\n\n // Should show validation error and NOT call onContinue\n const output = lastFrame();\n expect(output).toContain(\"Select at least one skill\");\n expect(onContinue).not.toHaveBeenCalled();\n });\n\n it(\"should call onContinue when validation passes\", async () => {\n const onContinue = vi.fn();\n const { stdin, unmount } = renderStepBuild({\n onContinue,\n selections: {\n \"web-framework\": [\"web-framework-react\"],\n \"web-styling\": [\"web-styling-tailwind\"],\n },\n });\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n\n // Press Enter to continue with required selections\n stdin.write(ENTER);\n await delay(INPUT_DELAY_MS);\n\n expect(onContinue).toHaveBeenCalled();\n });\n });\n});\n\ndescribe(\"getSkillDisplayLabel\", () => {\n it(\"should return displayName when available\", () => {\n expect(getSkillDisplayLabel({ displayName: \"react\", id: \"web-framework-react\" })).toBe(\"react\");\n });\n\n it(\"should return id when no displayName\", () => {\n expect(getSkillDisplayLabel({ id: \"web-framework-react\" })).toBe(\"web-framework-react\");\n });\n\n it(\"should prefer displayName over id\", () => {\n expect(\n getSkillDisplayLabel({ displayName: \"scss-modules\", id: \"web-styling-scss-modules\" }),\n ).toBe(\"scss-modules\");\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
StepConfirm
|
|
4
|
-
} from "../../chunk-
|
|
5
|
-
import "../../chunk-
|
|
4
|
+
} from "../../chunk-5TMB53BV.js";
|
|
5
|
+
import "../../chunk-YRVTXSXP.js";
|
|
6
6
|
import "../../chunk-T4EXUIBY.js";
|
|
7
|
-
import "../../chunk-
|
|
7
|
+
import "../../chunk-BK7TANUV.js";
|
|
8
8
|
import "../../chunk-DHET7RCE.js";
|
|
9
9
|
export {
|
|
10
10
|
StepConfirm
|
|
@@ -18,16 +18,16 @@ import {
|
|
|
18
18
|
} from "../../chunk-XY3XDVMI.js";
|
|
19
19
|
import {
|
|
20
20
|
StepConfirm
|
|
21
|
-
} from "../../chunk-
|
|
22
|
-
import "../../chunk-
|
|
21
|
+
} from "../../chunk-5TMB53BV.js";
|
|
22
|
+
import "../../chunk-YRVTXSXP.js";
|
|
23
23
|
import {
|
|
24
24
|
useWizardStore
|
|
25
|
-
} from "../../chunk-
|
|
26
|
-
import "../../chunk-
|
|
27
|
-
import "../../chunk-
|
|
25
|
+
} from "../../chunk-423MJ6DT.js";
|
|
26
|
+
import "../../chunk-SILUTTV7.js";
|
|
27
|
+
import "../../chunk-TTXV55NQ.js";
|
|
28
28
|
import "../../chunk-T4EXUIBY.js";
|
|
29
|
-
import "../../chunk-
|
|
30
|
-
import "../../chunk-
|
|
29
|
+
import "../../chunk-XJXJZ2MJ.js";
|
|
30
|
+
import "../../chunk-BK7TANUV.js";
|
|
31
31
|
import {
|
|
32
32
|
init_esm_shims
|
|
33
33
|
} from "../../chunk-DHET7RCE.js";
|
|
@@ -181,8 +181,11 @@ describe("StepConfirm component", () => {
|
|
|
181
181
|
onComplete,
|
|
182
182
|
selectedDomains: ["web", "api"],
|
|
183
183
|
domainSelections: {
|
|
184
|
-
web: {
|
|
185
|
-
|
|
184
|
+
web: {
|
|
185
|
+
"web-framework": ["web-framework-react"],
|
|
186
|
+
"web-styling": ["web-styling-scss-modules"]
|
|
187
|
+
},
|
|
188
|
+
api: { "api-api": ["api-framework-hono"] }
|
|
186
189
|
},
|
|
187
190
|
technologyCount: 3,
|
|
188
191
|
skillCount: 3,
|
|
@@ -206,8 +209,11 @@ describe("StepConfirm component", () => {
|
|
|
206
209
|
onComplete,
|
|
207
210
|
selectedDomains: ["web", "api"],
|
|
208
211
|
domainSelections: {
|
|
209
|
-
web: {
|
|
210
|
-
|
|
212
|
+
web: {
|
|
213
|
+
"web-framework": ["web-framework-react"],
|
|
214
|
+
"web-styling": ["web-styling-scss-modules"]
|
|
215
|
+
},
|
|
216
|
+
api: { "api-api": ["api-framework-hono"] }
|
|
211
217
|
},
|
|
212
218
|
technologyCount: 3,
|
|
213
219
|
skillCount: 3,
|
|
@@ -234,7 +240,7 @@ describe("StepConfirm component", () => {
|
|
|
234
240
|
onComplete,
|
|
235
241
|
selectedDomains: ["web"],
|
|
236
242
|
domainSelections: {
|
|
237
|
-
web: { framework: ["web-framework-react"] }
|
|
243
|
+
web: { "web-framework": ["web-framework-react"] }
|
|
238
244
|
},
|
|
239
245
|
technologyCount: 1,
|
|
240
246
|
skillCount: 1,
|
|
@@ -258,7 +264,7 @@ describe("StepConfirm component", () => {
|
|
|
258
264
|
onComplete,
|
|
259
265
|
selectedDomains: ["web", "api"],
|
|
260
266
|
domainSelections: {
|
|
261
|
-
web: { framework: ["web-framework-react"] },
|
|
267
|
+
web: { "web-framework": ["web-framework-react"] },
|
|
262
268
|
api: {}
|
|
263
269
|
// Empty selections
|
|
264
270
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/components/wizard/step-confirm.test.tsx"],"sourcesContent":["import { render } from \"ink-testing-library\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { StepConfirm } from \"./step-confirm\";\nimport { useWizardStore } from \"../../stores/wizard-store\";\nimport { ENTER, ESCAPE, RENDER_DELAY_MS, delay } from \"../../lib/__tests__/test-constants\";\n\ndescribe(\"StepConfirm component\", () => {\n let cleanup: (() => void) | undefined;\n\n beforeEach(() => {\n useWizardStore.getState().reset();\n });\n\n afterEach(() => {\n cleanup?.();\n cleanup = undefined;\n });\n\n describe(\"stack path\", () => {\n it(\"should render stack name in title\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install nextjs-fullstack\");\n });\n\n it(\"should show technology count\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Technologies:\");\n expect(output).toContain(\"12\");\n });\n\n it(\"should show skill count with verified label\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Skills:\");\n expect(output).toContain(\"(all verified)\");\n });\n\n it(\"should show install mode as Plugin\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Install mode:\");\n expect(output).toContain(\"Plugin\");\n });\n\n it(\"should show install mode as Local\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Install mode:\");\n expect(output).toContain(\"Local\");\n });\n\n it(\"should render confirm step content\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install\");\n });\n });\n\n describe(\"scratch path\", () => {\n it(\"should render custom stack title with domain names\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\", \"api\"]}\n domainSelections={{\n web: { framework: [\"web-framework-react\"], styling: [\"web-styling-scss-modules\"] },\n api: { api: [\"api-framework-hono\"] },\n }}\n technologyCount={3}\n skillCount={3}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install your custom stack\");\n expect(output).toContain(\"Web + API\");\n });\n\n it(\"should show domain breakdown with technologies\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\", \"api\"]}\n domainSelections={{\n web: { framework: [\"web-framework-react\"], styling: [\"web-styling-scss-modules\"] },\n api: { api: [\"api-framework-hono\"] },\n }}\n technologyCount={3}\n skillCount={3}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Web:\");\n expect(output).toContain(\"react\");\n expect(output).toContain(\"scss-modules\");\n expect(output).toContain(\"API:\");\n expect(output).toContain(\"hono\");\n });\n\n it(\"should handle single domain without plus sign\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\"]}\n domainSelections={{\n web: { framework: [\"web-framework-react\"] },\n }}\n technologyCount={1}\n skillCount={1}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"(Web)\");\n expect(output).not.toContain(\"+\");\n });\n\n it(\"should skip domains with no selections\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\", \"api\"]}\n domainSelections={{\n web: { framework: [\"web-framework-react\"] },\n api: {}, // Empty selections\n }}\n technologyCount={1}\n skillCount={1}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Web:\");\n expect(output).toContain(\"react\");\n // API section should not appear since no technologies selected\n const lines = output?.split(\"\\n\") || [];\n const apiLine = lines.find((line) => line.includes(\"API:\") && line.includes(\"hono\"));\n expect(apiLine).toBeUndefined();\n });\n });\n\n describe(\"keyboard navigation\", () => {\n it(\"should call onComplete when Enter is pressed\", async () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { stdin, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n await stdin.write(ENTER);\n await delay(RENDER_DELAY_MS);\n\n expect(onComplete).toHaveBeenCalled();\n });\n\n it(\"should call onBack when Escape is pressed\", async () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { stdin, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n await stdin.write(ESCAPE);\n await delay(RENDER_DELAY_MS);\n\n expect(onBack).toHaveBeenCalled();\n expect(onComplete).not.toHaveBeenCalled();\n });\n\n it(\"should not call onBack when Escape is pressed but onBack is not provided\", async () => {\n const onComplete = vi.fn();\n\n const { stdin, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n // No onBack provided\n />,\n );\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n await stdin.write(ESCAPE);\n await delay(RENDER_DELAY_MS);\n\n // Should not crash and onComplete should not be called\n expect(onComplete).not.toHaveBeenCalled();\n });\n });\n\n describe(\"default props\", () => {\n it(\"should render custom stack title when no stack name provided\", () => {\n const onComplete = vi.fn();\n\n const { lastFrame, unmount } = render(<StepConfirm onComplete={onComplete} />);\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install your custom stack\");\n });\n\n it(\"should not show stats when not provided\", () => {\n const onComplete = vi.fn();\n\n const { lastFrame, unmount } = render(<StepConfirm onComplete={onComplete} />);\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).not.toContain(\"Technologies:\");\n expect(output).not.toContain(\"Skills:\");\n expect(output).not.toContain(\"Install mode:\");\n });\n });\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/components/wizard/step-confirm.test.tsx"],"sourcesContent":["import { render } from \"ink-testing-library\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { StepConfirm } from \"./step-confirm\";\nimport { useWizardStore } from \"../../stores/wizard-store\";\nimport { ENTER, ESCAPE, RENDER_DELAY_MS, delay } from \"../../lib/__tests__/test-constants\";\n\ndescribe(\"StepConfirm component\", () => {\n let cleanup: (() => void) | undefined;\n\n beforeEach(() => {\n useWizardStore.getState().reset();\n });\n\n afterEach(() => {\n cleanup?.();\n cleanup = undefined;\n });\n\n describe(\"stack path\", () => {\n it(\"should render stack name in title\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install nextjs-fullstack\");\n });\n\n it(\"should show technology count\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Technologies:\");\n expect(output).toContain(\"12\");\n });\n\n it(\"should show skill count with verified label\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Skills:\");\n expect(output).toContain(\"(all verified)\");\n });\n\n it(\"should show install mode as Plugin\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Install mode:\");\n expect(output).toContain(\"Plugin\");\n });\n\n it(\"should show install mode as Local\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Install mode:\");\n expect(output).toContain(\"Local\");\n });\n\n it(\"should render confirm step content\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install\");\n });\n });\n\n describe(\"scratch path\", () => {\n it(\"should render custom stack title with domain names\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\", \"api\"]}\n domainSelections={{\n web: {\n \"web-framework\": [\"web-framework-react\"],\n \"web-styling\": [\"web-styling-scss-modules\"],\n },\n api: { \"api-api\": [\"api-framework-hono\"] },\n }}\n technologyCount={3}\n skillCount={3}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install your custom stack\");\n expect(output).toContain(\"Web + API\");\n });\n\n it(\"should show domain breakdown with technologies\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\", \"api\"]}\n domainSelections={{\n web: {\n \"web-framework\": [\"web-framework-react\"],\n \"web-styling\": [\"web-styling-scss-modules\"],\n },\n api: { \"api-api\": [\"api-framework-hono\"] },\n }}\n technologyCount={3}\n skillCount={3}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Web:\");\n expect(output).toContain(\"react\");\n expect(output).toContain(\"scss-modules\");\n expect(output).toContain(\"API:\");\n expect(output).toContain(\"hono\");\n });\n\n it(\"should handle single domain without plus sign\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\"]}\n domainSelections={{\n web: { \"web-framework\": [\"web-framework-react\"] },\n }}\n technologyCount={1}\n skillCount={1}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"(Web)\");\n expect(output).not.toContain(\"+\");\n });\n\n it(\"should skip domains with no selections\", () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { lastFrame, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n selectedDomains={[\"web\", \"api\"]}\n domainSelections={{\n web: { \"web-framework\": [\"web-framework-react\"] },\n api: {}, // Empty selections\n }}\n technologyCount={1}\n skillCount={1}\n installMode=\"local\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Web:\");\n expect(output).toContain(\"react\");\n // API section should not appear since no technologies selected\n const lines = output?.split(\"\\n\") || [];\n const apiLine = lines.find((line) => line.includes(\"API:\") && line.includes(\"hono\"));\n expect(apiLine).toBeUndefined();\n });\n });\n\n describe(\"keyboard navigation\", () => {\n it(\"should call onComplete when Enter is pressed\", async () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { stdin, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n await stdin.write(ENTER);\n await delay(RENDER_DELAY_MS);\n\n expect(onComplete).toHaveBeenCalled();\n });\n\n it(\"should call onBack when Escape is pressed\", async () => {\n const onComplete = vi.fn();\n const onBack = vi.fn();\n\n const { stdin, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n onBack={onBack}\n />,\n );\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n await stdin.write(ESCAPE);\n await delay(RENDER_DELAY_MS);\n\n expect(onBack).toHaveBeenCalled();\n expect(onComplete).not.toHaveBeenCalled();\n });\n\n it(\"should not call onBack when Escape is pressed but onBack is not provided\", async () => {\n const onComplete = vi.fn();\n\n const { stdin, unmount } = render(\n <StepConfirm\n onComplete={onComplete}\n stackName=\"nextjs-fullstack\"\n technologyCount={12}\n skillCount={12}\n installMode=\"plugin\"\n // No onBack provided\n />,\n );\n cleanup = unmount;\n\n await delay(RENDER_DELAY_MS);\n await stdin.write(ESCAPE);\n await delay(RENDER_DELAY_MS);\n\n // Should not crash and onComplete should not be called\n expect(onComplete).not.toHaveBeenCalled();\n });\n });\n\n describe(\"default props\", () => {\n it(\"should render custom stack title when no stack name provided\", () => {\n const onComplete = vi.fn();\n\n const { lastFrame, unmount } = render(<StepConfirm onComplete={onComplete} />);\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).toContain(\"Ready to install your custom stack\");\n });\n\n it(\"should not show stats when not provided\", () => {\n const onComplete = vi.fn();\n\n const { lastFrame, unmount } = render(<StepConfirm onComplete={onComplete} />);\n cleanup = unmount;\n\n const output = lastFrame();\n expect(output).not.toContain(\"Technologies:\");\n expect(output).not.toContain(\"Skills:\");\n expect(output).not.toContain(\"Install mode:\");\n });\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
StepRefine
|
|
4
|
-
} from "../../chunk-
|
|
4
|
+
} from "../../chunk-R52N7DBG.js";
|
|
5
5
|
import {
|
|
6
6
|
ARROW_DOWN,
|
|
7
7
|
ARROW_UP,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "../../chunk-XY3XDVMI.js";
|
|
24
24
|
import {
|
|
25
25
|
DEFAULT_BRANDING
|
|
26
|
-
} from "../../chunk-
|
|
26
|
+
} from "../../chunk-BK7TANUV.js";
|
|
27
27
|
import {
|
|
28
28
|
init_esm_shims
|
|
29
29
|
} from "../../chunk-DHET7RCE.js";
|