@sundaeswap/sprinkles 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Sprinkle/__tests__/encryption.test.js +22 -8
- package/dist/cjs/Sprinkle/__tests__/encryption.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/enhancements.test.js +37 -46
- package/dist/cjs/Sprinkle/__tests__/enhancements.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/field-utils.test.js +170 -0
- package/dist/cjs/Sprinkle/__tests__/field-utils.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js +283 -81
- package/dist/cjs/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/formatting.test.js +97 -0
- package/dist/cjs/Sprinkle/__tests__/formatting.test.js.map +1 -0
- package/dist/cjs/Sprinkle/__tests__/show-menu.test.js +97 -7
- package/dist/cjs/Sprinkle/__tests__/show-menu.test.js.map +1 -1
- package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js +30 -0
- package/dist/cjs/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
- package/dist/cjs/Sprinkle/encryption.js +131 -0
- package/dist/cjs/Sprinkle/encryption.js.map +1 -0
- package/dist/cjs/Sprinkle/index.js +427 -438
- package/dist/cjs/Sprinkle/index.js.map +1 -1
- package/dist/cjs/Sprinkle/menus/array-menu.js +195 -0
- package/dist/cjs/Sprinkle/menus/array-menu.js.map +1 -0
- package/dist/cjs/Sprinkle/menus/field-menu.js +161 -0
- package/dist/cjs/Sprinkle/menus/field-menu.js.map +1 -0
- package/dist/cjs/Sprinkle/menus/index.js +33 -0
- package/dist/cjs/Sprinkle/menus/index.js.map +1 -0
- package/dist/cjs/Sprinkle/menus/object-menu.js +324 -0
- package/dist/cjs/Sprinkle/menus/object-menu.js.map +1 -0
- package/dist/cjs/Sprinkle/prompts.js +459 -0
- package/dist/cjs/Sprinkle/prompts.js.map +1 -0
- package/dist/cjs/Sprinkle/schemas.js +97 -0
- package/dist/cjs/Sprinkle/schemas.js.map +1 -0
- package/dist/cjs/Sprinkle/tx-dialog.js +101 -0
- package/dist/cjs/Sprinkle/tx-dialog.js.map +1 -0
- package/dist/cjs/Sprinkle/type-guards.js +89 -0
- package/dist/cjs/Sprinkle/type-guards.js.map +1 -0
- package/dist/cjs/Sprinkle/types.js +73 -0
- package/dist/cjs/Sprinkle/types.js.map +1 -0
- package/dist/cjs/Sprinkle/utils/field-utils.js +154 -0
- package/dist/cjs/Sprinkle/utils/field-utils.js.map +1 -0
- package/dist/cjs/Sprinkle/utils/formatting.js +126 -0
- package/dist/cjs/Sprinkle/utils/formatting.js.map +1 -0
- package/dist/cjs/Sprinkle/utils/index.js +56 -0
- package/dist/cjs/Sprinkle/utils/index.js.map +1 -0
- package/dist/cjs/Sprinkle/wallet.js +98 -0
- package/dist/cjs/Sprinkle/wallet.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/encryption.test.js +22 -8
- package/dist/esm/Sprinkle/__tests__/encryption.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/enhancements.test.js +37 -46
- package/dist/esm/Sprinkle/__tests__/enhancements.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/field-utils.test.js +168 -0
- package/dist/esm/Sprinkle/__tests__/field-utils.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js +284 -82
- package/dist/esm/Sprinkle/__tests__/fill-in-struct.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/formatting.test.js +95 -0
- package/dist/esm/Sprinkle/__tests__/formatting.test.js.map +1 -0
- package/dist/esm/Sprinkle/__tests__/show-menu.test.js +98 -8
- package/dist/esm/Sprinkle/__tests__/show-menu.test.js.map +1 -1
- package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js +30 -0
- package/dist/esm/Sprinkle/__tests__/tx-dialog.test.js.map +1 -1
- package/dist/esm/Sprinkle/encryption.js +117 -0
- package/dist/esm/Sprinkle/encryption.js.map +1 -0
- package/dist/esm/Sprinkle/index.js +248 -425
- package/dist/esm/Sprinkle/index.js.map +1 -1
- package/dist/esm/Sprinkle/menus/array-menu.js +190 -0
- package/dist/esm/Sprinkle/menus/array-menu.js.map +1 -0
- package/dist/esm/Sprinkle/menus/field-menu.js +155 -0
- package/dist/esm/Sprinkle/menus/field-menu.js.map +1 -0
- package/dist/esm/Sprinkle/menus/index.js +8 -0
- package/dist/esm/Sprinkle/menus/index.js.map +1 -0
- package/dist/esm/Sprinkle/menus/object-menu.js +318 -0
- package/dist/esm/Sprinkle/menus/object-menu.js.map +1 -0
- package/dist/esm/Sprinkle/prompts.js +443 -0
- package/dist/esm/Sprinkle/prompts.js.map +1 -0
- package/dist/esm/Sprinkle/schemas.js +91 -0
- package/dist/esm/Sprinkle/schemas.js.map +1 -0
- package/dist/esm/Sprinkle/tx-dialog.js +90 -0
- package/dist/esm/Sprinkle/tx-dialog.js.map +1 -0
- package/dist/esm/Sprinkle/type-guards.js +66 -0
- package/dist/esm/Sprinkle/type-guards.js.map +1 -0
- package/dist/esm/Sprinkle/types.js +66 -0
- package/dist/esm/Sprinkle/types.js.map +1 -0
- package/dist/esm/Sprinkle/utils/field-utils.js +145 -0
- package/dist/esm/Sprinkle/utils/field-utils.js.map +1 -0
- package/dist/esm/Sprinkle/utils/formatting.js +118 -0
- package/dist/esm/Sprinkle/utils/formatting.js.map +1 -0
- package/dist/esm/Sprinkle/utils/index.js +7 -0
- package/dist/esm/Sprinkle/utils/index.js.map +1 -0
- package/dist/esm/Sprinkle/wallet.js +90 -0
- package/dist/esm/Sprinkle/wallet.js.map +1 -0
- package/dist/types/Sprinkle/encryption.d.ts +43 -0
- package/dist/types/Sprinkle/encryption.d.ts.map +1 -0
- package/dist/types/Sprinkle/index.d.ts +17 -177
- package/dist/types/Sprinkle/index.d.ts.map +1 -1
- package/dist/types/Sprinkle/menus/array-menu.d.ts +31 -0
- package/dist/types/Sprinkle/menus/array-menu.d.ts.map +1 -0
- package/dist/types/Sprinkle/menus/field-menu.d.ts +34 -0
- package/dist/types/Sprinkle/menus/field-menu.d.ts.map +1 -0
- package/dist/types/Sprinkle/menus/index.d.ts +10 -0
- package/dist/types/Sprinkle/menus/index.d.ts.map +1 -0
- package/dist/types/Sprinkle/menus/object-menu.d.ts +34 -0
- package/dist/types/Sprinkle/menus/object-menu.d.ts.map +1 -0
- package/dist/types/Sprinkle/prompts.d.ts +119 -0
- package/dist/types/Sprinkle/prompts.d.ts.map +1 -0
- package/dist/types/Sprinkle/schemas.d.ts +125 -0
- package/dist/types/Sprinkle/schemas.d.ts.map +1 -0
- package/dist/types/Sprinkle/tx-dialog.d.ts +37 -0
- package/dist/types/Sprinkle/tx-dialog.d.ts.map +1 -0
- package/dist/types/Sprinkle/type-guards.d.ts +45 -0
- package/dist/types/Sprinkle/type-guards.d.ts.map +1 -0
- package/dist/types/Sprinkle/types.d.ts +115 -0
- package/dist/types/Sprinkle/types.d.ts.map +1 -0
- package/dist/types/Sprinkle/utils/field-utils.d.ts +47 -0
- package/dist/types/Sprinkle/utils/field-utils.d.ts.map +1 -0
- package/dist/types/Sprinkle/utils/formatting.d.ts +30 -0
- package/dist/types/Sprinkle/utils/formatting.d.ts.map +1 -0
- package/dist/types/Sprinkle/wallet.d.ts +27 -0
- package/dist/types/Sprinkle/wallet.d.ts.map +1 -0
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Sprinkle/__tests__/encryption.test.ts +23 -8
- package/src/Sprinkle/__tests__/enhancements.test.ts +34 -47
- package/src/Sprinkle/__tests__/field-utils.test.ts +191 -0
- package/src/Sprinkle/__tests__/fill-in-struct.test.ts +301 -86
- package/src/Sprinkle/__tests__/formatting.test.ts +115 -0
- package/src/Sprinkle/__tests__/show-menu.test.ts +102 -8
- package/src/Sprinkle/__tests__/tx-dialog.test.ts +30 -0
- package/src/Sprinkle/encryption.ts +130 -0
- package/src/Sprinkle/index.ts +368 -598
- package/src/Sprinkle/menus/array-menu.ts +191 -0
- package/src/Sprinkle/menus/field-menu.ts +145 -0
- package/src/Sprinkle/menus/index.ts +12 -0
- package/src/Sprinkle/menus/object-menu.ts +336 -0
- package/src/Sprinkle/prompts.ts +551 -0
- package/src/Sprinkle/schemas.ts +111 -0
- package/src/Sprinkle/tx-dialog.ts +100 -0
- package/src/Sprinkle/type-guards.ts +93 -0
- package/src/Sprinkle/types.ts +116 -0
- package/src/Sprinkle/utils/field-utils.ts +158 -0
- package/src/Sprinkle/utils/formatting.ts +127 -0
- package/src/Sprinkle/utils/index.ts +17 -0
- package/src/Sprinkle/wallet.ts +133 -0
|
@@ -10,11 +10,22 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
10
10
|
const mockSelect = (0, _bunTest.mock)();
|
|
11
11
|
const mockInput = (0, _bunTest.mock)();
|
|
12
12
|
const mockPassword = (0, _bunTest.mock)();
|
|
13
|
+
const mockSelectCancellable = (0, _bunTest.mock)();
|
|
14
|
+
const mockInputCancellable = (0, _bunTest.mock)();
|
|
15
|
+
const mockPasswordCancellable = (0, _bunTest.mock)();
|
|
13
16
|
_bunTest.mock.module("@inquirer/prompts", () => ({
|
|
14
17
|
select: mockSelect,
|
|
15
18
|
input: mockInput,
|
|
16
19
|
password: mockPassword
|
|
17
20
|
}));
|
|
21
|
+
_bunTest.mock.module("../prompts.js", () => ({
|
|
22
|
+
selectCancellable: mockSelectCancellable,
|
|
23
|
+
inputCancellable: mockInputCancellable,
|
|
24
|
+
passwordCancellable: mockPasswordCancellable,
|
|
25
|
+
confirmCancellable: (0, _bunTest.mock)(),
|
|
26
|
+
searchCancellable: (0, _bunTest.mock)(),
|
|
27
|
+
select: mockSelectCancellable
|
|
28
|
+
}));
|
|
18
29
|
(0, _bunTest.describe)("Encryption & Sensitive Fields", () => {
|
|
19
30
|
let tmpDir;
|
|
20
31
|
(0, _bunTest.beforeEach)(() => {
|
|
@@ -22,6 +33,9 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
22
33
|
mockSelect.mockClear();
|
|
23
34
|
mockInput.mockClear();
|
|
24
35
|
mockPassword.mockClear();
|
|
36
|
+
mockSelectCancellable.mockClear();
|
|
37
|
+
mockInputCancellable.mockClear();
|
|
38
|
+
mockPasswordCancellable.mockClear();
|
|
25
39
|
});
|
|
26
40
|
(0, _bunTest.afterEach)(() => {
|
|
27
41
|
fs.rmSync(tmpDir, {
|
|
@@ -38,14 +52,14 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
38
52
|
})
|
|
39
53
|
});
|
|
40
54
|
const sprinkle = new _index.Sprinkle(schema, tmpDir);
|
|
41
|
-
|
|
55
|
+
mockPasswordCancellable.mockResolvedValueOnce("my-secret");
|
|
42
56
|
const result = await sprinkle.FillInStruct(schema);
|
|
43
57
|
(0, _bunTest.expect)(result).toEqual({
|
|
44
58
|
secret: "my-secret"
|
|
45
59
|
});
|
|
46
|
-
(0, _bunTest.expect)(
|
|
47
|
-
(0, _bunTest.expect)(
|
|
48
|
-
(0, _bunTest.expect)(
|
|
60
|
+
(0, _bunTest.expect)(mockPasswordCancellable).toHaveBeenCalledTimes(1);
|
|
61
|
+
(0, _bunTest.expect)(mockPasswordCancellable.mock.calls[0][0].message).toBe("Enter secret");
|
|
62
|
+
(0, _bunTest.expect)(mockInputCancellable).not.toHaveBeenCalled();
|
|
49
63
|
});
|
|
50
64
|
(0, _bunTest.test)("uses input() for non-sensitive string fields", async () => {
|
|
51
65
|
const schema = _index.Type.Object({
|
|
@@ -54,13 +68,13 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
54
68
|
})
|
|
55
69
|
});
|
|
56
70
|
const sprinkle = new _index.Sprinkle(schema, tmpDir);
|
|
57
|
-
|
|
71
|
+
mockInputCancellable.mockResolvedValueOnce("visible");
|
|
58
72
|
const result = await sprinkle.FillInStruct(schema);
|
|
59
73
|
(0, _bunTest.expect)(result).toEqual({
|
|
60
74
|
name: "visible"
|
|
61
75
|
});
|
|
62
|
-
(0, _bunTest.expect)(
|
|
63
|
-
(0, _bunTest.expect)(
|
|
76
|
+
(0, _bunTest.expect)(mockInputCancellable).toHaveBeenCalledTimes(1);
|
|
77
|
+
(0, _bunTest.expect)(mockPasswordCancellable).not.toHaveBeenCalled();
|
|
64
78
|
});
|
|
65
79
|
(0, _bunTest.test)("does not remember sensitive field as default", async () => {
|
|
66
80
|
const schema = _index.Type.String({
|
|
@@ -69,7 +83,7 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
69
83
|
const sprinkle = new _index.Sprinkle(_index.Type.Object({
|
|
70
84
|
p: _index.Type.String()
|
|
71
85
|
}), tmpDir);
|
|
72
|
-
|
|
86
|
+
mockPasswordCancellable.mockResolvedValueOnce("secret-val");
|
|
73
87
|
await sprinkle.FillInStruct(schema);
|
|
74
88
|
(0, _bunTest.expect)(sprinkle.defaults["string"]).toBeUndefined();
|
|
75
89
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption.test.js","names":["_bunTest","require","_index","fs","_interopRequireWildcard","path","os","_testHelpers","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","mockSelect","mock","mockInput","mockPassword","module","select","input","password","describe","tmpDir","beforeEach","mkdtempSync","join","tmpdir","mockClear","afterEach","rmSync","recursive","force","test","schema","Type","secret","String","sensitive","title","sprinkle","Sprinkle","mockResolvedValueOnce","result","FillInStruct","expect","toEqual","toHaveBeenCalledTimes","calls","message","toBe","not","toHaveBeenCalled","name","p","defaults","toBeUndefined","withProfile","encryption","encrypt","plain","decrypt","cipher","replace","settings","saveSettings","content","readFileSync","parsed","JSON","parse","sprinkle1","sprinkle2","loadProfile","wallet","key","address","Union","type","Literal","privateKey","outerSchema","network","count","BigInt","opts","Buffer","from","toString","s1","s2","mkdirSync","writeFileSync","stringify","New","c","options","toBeDefined","profileId"],"sources":["../../../../src/Sprinkle/__tests__/encryption.test.ts"],"sourcesContent":["import { describe, expect, test, mock, beforeEach, afterEach } from \"bun:test\";\nimport { Sprinkle, Type } from \"../index.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { withProfile } from \"./test-helpers.js\";\n\nconst mockSelect = mock();\nconst mockInput = mock();\nconst mockPassword = mock();\n\nmock.module(\"@inquirer/prompts\", () => ({\n select: mockSelect,\n input: mockInput,\n password: mockPassword,\n}));\n\ndescribe(\"Encryption & Sensitive Fields\", () => {\n let tmpDir: string;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sprinkles-enc-test-\"));\n mockSelect.mockClear();\n mockInput.mockClear();\n mockPassword.mockClear();\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n describe(\"sensitive field prompts\", () => {\n test(\"uses password() for sensitive string fields\", async () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true, title: \"Enter secret\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockPassword.mockResolvedValueOnce(\"my-secret\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ secret: \"my-secret\" });\n expect(mockPassword).toHaveBeenCalledTimes(1);\n expect(mockPassword.mock.calls[0][0].message).toBe(\"Enter secret\");\n expect(mockInput).not.toHaveBeenCalled();\n });\n\n test(\"uses input() for non-sensitive string fields\", async () => {\n const schema = Type.Object({\n name: Type.String({ title: \"Enter name\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockInput.mockResolvedValueOnce(\"visible\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ name: \"visible\" });\n expect(mockInput).toHaveBeenCalledTimes(1);\n expect(mockPassword).not.toHaveBeenCalled();\n });\n\n test(\"does not remember sensitive field as default\", async () => {\n const schema = Type.String({ sensitive: true });\n const sprinkle = new Sprinkle(Type.Object({ p: Type.String() }), tmpDir);\n\n mockPassword.mockResolvedValueOnce(\"secret-val\");\n\n await sprinkle.FillInStruct(schema);\n expect(sprinkle.defaults[\"string\"]).toBeUndefined();\n });\n });\n\n describe(\"encryption on save/load\", () => {\n test(\"encrypts sensitive fields when saving with encryption configured\", () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = { name: \"visible\", secret: \"hidden\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.name).toBe(\"visible\");\n expect(parsed.settings.secret).toBe(\"ENC:hidden\");\n });\n\n test(\"decrypts sensitive fields when loading with encryption configured\", async () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n\n // First save with encryption\n const sprinkle1 = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle1.settings = { name: \"visible\", secret: \"hidden\" } as any;\n sprinkle1.saveSettings();\n\n // Then load with same encryption\n const sprinkle2 = new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n });\n await sprinkle2.loadProfile(\"test\");\n\n expect(sprinkle2.settings).toEqual({ name: \"visible\", secret: \"hidden\" });\n });\n\n test(\"does not encrypt when no encryption configured\", () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(new Sprinkle(schema, tmpDir));\n sprinkle.settings = { secret: \"plain-value\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.secret).toBe(\"plain-value\");\n });\n\n test(\"encrypts nested sensitive fields\", () => {\n const schema = Type.Object({\n wallet: Type.Object({\n key: Type.String({ sensitive: true }),\n address: Type.String(),\n }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { key: \"secret-key\", address: \"addr1...\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.key).toBe(\"ENC:secret-key\");\n expect(parsed.settings.wallet.address).toBe(\"addr1...\");\n });\n\n test(\"handles sensitive fields in union variants\", () => {\n const schema = Type.Union([\n Type.Object({\n type: Type.Literal(\"hot\"),\n privateKey: Type.String({ sensitive: true }),\n }),\n Type.Object({\n type: Type.Literal(\"cold\"),\n address: Type.String(),\n }),\n ]);\n const outerSchema = Type.Object({ wallet: schema });\n const sprinkle = withProfile(\n new Sprinkle(outerSchema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { type: \"hot\", privateKey: \"my-key\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.privateKey).toBe(\"ENC:my-key\");\n });\n\n test(\"round-trip with encryption preserves all data\", async () => {\n const schema = Type.Object({\n network: Type.String(),\n secret: Type.String({ sensitive: true }),\n count: Type.BigInt(),\n });\n const opts = {\n encryption: {\n encrypt: (plain: string) => Buffer.from(plain).toString(\"base64\"),\n decrypt: async (cipher: string) =>\n Buffer.from(cipher, \"base64\").toString(),\n },\n };\n const s1 = withProfile(new Sprinkle(schema, tmpDir, opts));\n s1.settings = {\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n } as any;\n s1.saveSettings();\n\n const s2 = new Sprinkle(schema, tmpDir, opts);\n await s2.loadProfile(\"test\");\n\n expect(s2.settings).toEqual({\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n });\n });\n });\n\n describe(\"Sprinkle.New with options\", () => {\n test(\"passes options through to instance and migrates legacy\", async () => {\n const schema = Type.Object({ name: Type.String() });\n\n // Write legacy settings file so New triggers migration\n fs.mkdirSync(tmpDir, { recursive: true });\n fs.writeFileSync(\n path.join(tmpDir, \"settings.json\"),\n JSON.stringify({ settings: { name: \"test\" }, defaults: {} }),\n );\n\n const sprinkle = await Sprinkle.New(schema, tmpDir, {\n encryption: {\n encrypt: (p) => p,\n decrypt: async (c) => c,\n },\n });\n\n expect(sprinkle.options.encryption).toBeDefined();\n expect(sprinkle.profileId).toBe(\"default\");\n expect(sprinkle.settings).toEqual({ name: \"test\" });\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"encryption.test.js","names":["_bunTest","require","_index","fs","_interopRequireWildcard","path","os","_testHelpers","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","mockSelect","mock","mockInput","mockPassword","mockSelectCancellable","mockInputCancellable","mockPasswordCancellable","module","select","input","password","selectCancellable","inputCancellable","passwordCancellable","confirmCancellable","searchCancellable","describe","tmpDir","beforeEach","mkdtempSync","join","tmpdir","mockClear","afterEach","rmSync","recursive","force","test","schema","Type","secret","String","sensitive","title","sprinkle","Sprinkle","mockResolvedValueOnce","result","FillInStruct","expect","toEqual","toHaveBeenCalledTimes","calls","message","toBe","not","toHaveBeenCalled","name","p","defaults","toBeUndefined","withProfile","encryption","encrypt","plain","decrypt","cipher","replace","settings","saveSettings","content","readFileSync","parsed","JSON","parse","sprinkle1","sprinkle2","loadProfile","wallet","key","address","Union","type","Literal","privateKey","outerSchema","network","count","BigInt","opts","Buffer","from","toString","s1","s2","mkdirSync","writeFileSync","stringify","New","c","options","toBeDefined","profileId"],"sources":["../../../../src/Sprinkle/__tests__/encryption.test.ts"],"sourcesContent":["import { describe, expect, test, mock, beforeEach, afterEach } from \"bun:test\";\nimport { Sprinkle, Type } from \"../index.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport { withProfile } from \"./test-helpers.js\";\n\nconst mockSelect = mock();\nconst mockInput = mock();\nconst mockPassword = mock();\nconst mockSelectCancellable = mock();\nconst mockInputCancellable = mock();\nconst mockPasswordCancellable = mock();\n\nmock.module(\"@inquirer/prompts\", () => ({\n select: mockSelect,\n input: mockInput,\n password: mockPassword,\n}));\n\nmock.module(\"../prompts.js\", () => ({\n selectCancellable: mockSelectCancellable,\n inputCancellable: mockInputCancellable,\n passwordCancellable: mockPasswordCancellable,\n confirmCancellable: mock(),\n searchCancellable: mock(),\n select: mockSelectCancellable,\n}));\n\ndescribe(\"Encryption & Sensitive Fields\", () => {\n let tmpDir: string;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"sprinkles-enc-test-\"));\n mockSelect.mockClear();\n mockInput.mockClear();\n mockPassword.mockClear();\n mockSelectCancellable.mockClear();\n mockInputCancellable.mockClear();\n mockPasswordCancellable.mockClear();\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n describe(\"sensitive field prompts\", () => {\n test(\"uses password() for sensitive string fields\", async () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true, title: \"Enter secret\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockPasswordCancellable.mockResolvedValueOnce(\"my-secret\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ secret: \"my-secret\" });\n expect(mockPasswordCancellable).toHaveBeenCalledTimes(1);\n expect(mockPasswordCancellable.mock.calls[0][0].message).toBe(\"Enter secret\");\n expect(mockInputCancellable).not.toHaveBeenCalled();\n });\n\n test(\"uses input() for non-sensitive string fields\", async () => {\n const schema = Type.Object({\n name: Type.String({ title: \"Enter name\" }),\n });\n const sprinkle = new Sprinkle(schema, tmpDir);\n\n mockInputCancellable.mockResolvedValueOnce(\"visible\");\n\n const result = await sprinkle.FillInStruct(schema);\n expect(result).toEqual({ name: \"visible\" });\n expect(mockInputCancellable).toHaveBeenCalledTimes(1);\n expect(mockPasswordCancellable).not.toHaveBeenCalled();\n });\n\n test(\"does not remember sensitive field as default\", async () => {\n const schema = Type.String({ sensitive: true });\n const sprinkle = new Sprinkle(Type.Object({ p: Type.String() }), tmpDir);\n\n mockPasswordCancellable.mockResolvedValueOnce(\"secret-val\");\n\n await sprinkle.FillInStruct(schema);\n expect(sprinkle.defaults[\"string\"]).toBeUndefined();\n });\n });\n\n describe(\"encryption on save/load\", () => {\n test(\"encrypts sensitive fields when saving with encryption configured\", () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = { name: \"visible\", secret: \"hidden\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.name).toBe(\"visible\");\n expect(parsed.settings.secret).toBe(\"ENC:hidden\");\n });\n\n test(\"decrypts sensitive fields when loading with encryption configured\", async () => {\n const schema = Type.Object({\n name: Type.String(),\n secret: Type.String({ sensitive: true }),\n });\n\n // First save with encryption\n const sprinkle1 = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle1.settings = { name: \"visible\", secret: \"hidden\" } as any;\n sprinkle1.saveSettings();\n\n // Then load with same encryption\n const sprinkle2 = new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n });\n await sprinkle2.loadProfile(\"test\");\n\n expect(sprinkle2.settings).toEqual({ name: \"visible\", secret: \"hidden\" });\n });\n\n test(\"does not encrypt when no encryption configured\", () => {\n const schema = Type.Object({\n secret: Type.String({ sensitive: true }),\n });\n const sprinkle = withProfile(new Sprinkle(schema, tmpDir));\n sprinkle.settings = { secret: \"plain-value\" } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.secret).toBe(\"plain-value\");\n });\n\n test(\"encrypts nested sensitive fields\", () => {\n const schema = Type.Object({\n wallet: Type.Object({\n key: Type.String({ sensitive: true }),\n address: Type.String(),\n }),\n });\n const sprinkle = withProfile(\n new Sprinkle(schema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { key: \"secret-key\", address: \"addr1...\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.key).toBe(\"ENC:secret-key\");\n expect(parsed.settings.wallet.address).toBe(\"addr1...\");\n });\n\n test(\"handles sensitive fields in union variants\", () => {\n const schema = Type.Union([\n Type.Object({\n type: Type.Literal(\"hot\"),\n privateKey: Type.String({ sensitive: true }),\n }),\n Type.Object({\n type: Type.Literal(\"cold\"),\n address: Type.String(),\n }),\n ]);\n const outerSchema = Type.Object({ wallet: schema });\n const sprinkle = withProfile(\n new Sprinkle(outerSchema, tmpDir, {\n encryption: {\n encrypt: (plain) => `ENC:${plain}`,\n decrypt: async (cipher) => cipher.replace(\"ENC:\", \"\"),\n },\n }),\n );\n sprinkle.settings = {\n wallet: { type: \"hot\", privateKey: \"my-key\" },\n } as any;\n\n sprinkle.saveSettings();\n\n const content = fs.readFileSync(\n path.join(tmpDir, \"profiles\", \"test.json\"),\n \"utf-8\",\n );\n const parsed = JSON.parse(content);\n expect(parsed.settings.wallet.privateKey).toBe(\"ENC:my-key\");\n });\n\n test(\"round-trip with encryption preserves all data\", async () => {\n const schema = Type.Object({\n network: Type.String(),\n secret: Type.String({ sensitive: true }),\n count: Type.BigInt(),\n });\n const opts = {\n encryption: {\n encrypt: (plain: string) => Buffer.from(plain).toString(\"base64\"),\n decrypt: async (cipher: string) =>\n Buffer.from(cipher, \"base64\").toString(),\n },\n };\n const s1 = withProfile(new Sprinkle(schema, tmpDir, opts));\n s1.settings = {\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n } as any;\n s1.saveSettings();\n\n const s2 = new Sprinkle(schema, tmpDir, opts);\n await s2.loadProfile(\"test\");\n\n expect(s2.settings).toEqual({\n network: \"mainnet\",\n secret: \"top-secret\",\n count: 42n,\n });\n });\n });\n\n describe(\"Sprinkle.New with options\", () => {\n test(\"passes options through to instance and migrates legacy\", async () => {\n const schema = Type.Object({ name: Type.String() });\n\n // Write legacy settings file so New triggers migration\n fs.mkdirSync(tmpDir, { recursive: true });\n fs.writeFileSync(\n path.join(tmpDir, \"settings.json\"),\n JSON.stringify({ settings: { name: \"test\" }, defaults: {} }),\n );\n\n const sprinkle = await Sprinkle.New(schema, tmpDir, {\n encryption: {\n encrypt: (p) => p,\n decrypt: async (c) => c,\n },\n });\n\n expect(sprinkle.options.encryption).toBeDefined();\n expect(sprinkle.profileId).toBe(\"default\");\n expect(sprinkle.settings).toEqual({ name: \"test\" });\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -5,12 +5,23 @@ var _index = require("../index.js");
|
|
|
5
5
|
const mockSelect = (0, _bunTest.mock)();
|
|
6
6
|
const mockInput = (0, _bunTest.mock)();
|
|
7
7
|
const mockPassword = (0, _bunTest.mock)();
|
|
8
|
-
const
|
|
8
|
+
const mockSelectCancellable = (0, _bunTest.mock)();
|
|
9
|
+
const mockInputCancellable = (0, _bunTest.mock)();
|
|
10
|
+
const mockPasswordCancellable = (0, _bunTest.mock)();
|
|
11
|
+
const mockConfirmCancellable = (0, _bunTest.mock)();
|
|
12
|
+
const mockSearchCancellable = (0, _bunTest.mock)();
|
|
9
13
|
_bunTest.mock.module("@inquirer/prompts", () => ({
|
|
10
14
|
select: mockSelect,
|
|
11
15
|
input: mockInput,
|
|
12
|
-
password: mockPassword
|
|
13
|
-
|
|
16
|
+
password: mockPassword
|
|
17
|
+
}));
|
|
18
|
+
_bunTest.mock.module("../prompts.js", () => ({
|
|
19
|
+
selectCancellable: mockSelectCancellable,
|
|
20
|
+
inputCancellable: mockInputCancellable,
|
|
21
|
+
passwordCancellable: mockPasswordCancellable,
|
|
22
|
+
confirmCancellable: mockConfirmCancellable,
|
|
23
|
+
searchCancellable: mockSearchCancellable,
|
|
24
|
+
select: mockSelectCancellable
|
|
14
25
|
}));
|
|
15
26
|
(0, _bunTest.describe)("beforeShow hook (2.2)", () => {
|
|
16
27
|
let sprinkle;
|
|
@@ -23,13 +34,14 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
23
34
|
name: "test"
|
|
24
35
|
};
|
|
25
36
|
mockSelect.mockClear();
|
|
37
|
+
mockSelectCancellable.mockClear();
|
|
26
38
|
});
|
|
27
39
|
(0, _bunTest.test)("calls beforeShow before rendering menu", async () => {
|
|
28
40
|
const callOrder = [];
|
|
29
41
|
const beforeShowFn = (0, _bunTest.mock)(async () => {
|
|
30
42
|
callOrder.push("beforeShow");
|
|
31
43
|
});
|
|
32
|
-
|
|
44
|
+
mockSelectCancellable.mockImplementation(async () => {
|
|
33
45
|
callOrder.push("select");
|
|
34
46
|
return -1; // exit
|
|
35
47
|
});
|
|
@@ -48,7 +60,7 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
48
60
|
});
|
|
49
61
|
(0, _bunTest.test)("passes sprinkle instance to beforeShow", async () => {
|
|
50
62
|
let receivedSprinkle;
|
|
51
|
-
|
|
63
|
+
mockSelectCancellable.mockResolvedValueOnce(-1);
|
|
52
64
|
const menu = {
|
|
53
65
|
title: "Test",
|
|
54
66
|
beforeShow: async s => {
|
|
@@ -63,7 +75,7 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
63
75
|
(0, _bunTest.expect)(receivedSprinkle).toBe(sprinkle);
|
|
64
76
|
});
|
|
65
77
|
(0, _bunTest.test)("menu works without beforeShow", async () => {
|
|
66
|
-
|
|
78
|
+
mockSelectCancellable.mockResolvedValueOnce(-1);
|
|
67
79
|
const menu = {
|
|
68
80
|
title: "Test",
|
|
69
81
|
items: [{
|
|
@@ -77,10 +89,10 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
77
89
|
});
|
|
78
90
|
(0, _bunTest.describe)("SearchSelect (2.3)", () => {
|
|
79
91
|
(0, _bunTest.beforeEach)(() => {
|
|
80
|
-
|
|
92
|
+
mockSearchCancellable.mockClear();
|
|
81
93
|
});
|
|
82
94
|
(0, _bunTest.test)("delegates to search prompt", async () => {
|
|
83
|
-
|
|
95
|
+
mockSearchCancellable.mockResolvedValueOnce("selected-value");
|
|
84
96
|
const result = await _index.Sprinkle.SearchSelect({
|
|
85
97
|
message: "Pick one",
|
|
86
98
|
source: () => [{
|
|
@@ -92,56 +104,35 @@ _bunTest.mock.module("@inquirer/prompts", () => ({
|
|
|
92
104
|
}]
|
|
93
105
|
});
|
|
94
106
|
(0, _bunTest.expect)(result).toBe("selected-value");
|
|
95
|
-
(0, _bunTest.expect)(
|
|
96
|
-
(0, _bunTest.expect)(
|
|
107
|
+
(0, _bunTest.expect)(mockSearchCancellable).toHaveBeenCalledTimes(1);
|
|
108
|
+
(0, _bunTest.expect)(mockSearchCancellable.mock.calls[0][0].message).toBe("Pick one");
|
|
97
109
|
});
|
|
98
110
|
(0, _bunTest.test)("passes source function through", async () => {
|
|
99
111
|
const sourceFn = (0, _bunTest.mock)(() => [{
|
|
100
112
|
name: "X",
|
|
101
113
|
value: "x"
|
|
102
114
|
}]);
|
|
103
|
-
|
|
115
|
+
mockSearchCancellable.mockResolvedValueOnce("x");
|
|
104
116
|
await _index.Sprinkle.SearchSelect({
|
|
105
117
|
message: "Search",
|
|
106
118
|
source: sourceFn
|
|
107
119
|
});
|
|
108
|
-
(0, _bunTest.expect)(
|
|
120
|
+
(0, _bunTest.expect)(mockSearchCancellable.mock.calls[0][0].source).toBe(sourceFn);
|
|
109
121
|
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
mockSelect.mockClear();
|
|
119
|
-
mockInput.mockClear();
|
|
120
|
-
});
|
|
121
|
-
(0, _bunTest.test)("skips optional field when user selects Skip", async () => {
|
|
122
|
-
const schema = _index.Type.Object({
|
|
123
|
-
name: _index.Type.String(),
|
|
124
|
-
nickname: _index.Type.Optional(_index.Type.String())
|
|
125
|
-
});
|
|
126
|
-
mockInput.mockResolvedValueOnce("Alice"); // name
|
|
127
|
-
mockSelect.mockResolvedValueOnce(false); // skip nickname
|
|
128
|
-
|
|
129
|
-
const result = await sprinkle.FillInStruct(schema);
|
|
130
|
-
(0, _bunTest.expect)(result.name).toBe("Alice");
|
|
131
|
-
(0, _bunTest.expect)(result.nickname).toBeUndefined();
|
|
132
|
-
});
|
|
133
|
-
(0, _bunTest.test)("fills optional field when user selects Yes", async () => {
|
|
134
|
-
const schema = _index.Type.Object({
|
|
135
|
-
name: _index.Type.String(),
|
|
136
|
-
nickname: _index.Type.Optional(_index.Type.String())
|
|
122
|
+
(0, _bunTest.test)("returns null when cancelled", async () => {
|
|
123
|
+
mockSearchCancellable.mockResolvedValueOnce(null);
|
|
124
|
+
const result = await _index.Sprinkle.SearchSelect({
|
|
125
|
+
message: "Pick one",
|
|
126
|
+
source: () => [{
|
|
127
|
+
name: "A",
|
|
128
|
+
value: "a"
|
|
129
|
+
}]
|
|
137
130
|
});
|
|
138
|
-
|
|
139
|
-
.mockResolvedValueOnce("Ali"); // nickname
|
|
140
|
-
mockSelect.mockResolvedValueOnce(true); // fill nickname
|
|
141
|
-
|
|
142
|
-
const result = await sprinkle.FillInStruct(schema);
|
|
143
|
-
(0, _bunTest.expect)(result.name).toBe("Alice");
|
|
144
|
-
(0, _bunTest.expect)(result.nickname).toBe("Ali");
|
|
131
|
+
(0, _bunTest.expect)(result).toBeNull();
|
|
145
132
|
});
|
|
146
133
|
});
|
|
134
|
+
|
|
135
|
+
// Note: "Optional type support (2.4)" tests removed - they tested the old sequential
|
|
136
|
+
// FillInStruct behavior. The new menu-based FillInStruct handles optional fields
|
|
137
|
+
// differently (via menu selection). See fill-in-struct.test.ts for comprehensive tests.
|
|
147
138
|
//# sourceMappingURL=enhancements.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enhancements.test.js","names":["_bunTest","require","_index","mockSelect","mock","mockInput","mockPassword","
|
|
1
|
+
{"version":3,"file":"enhancements.test.js","names":["_bunTest","require","_index","mockSelect","mock","mockInput","mockPassword","mockSelectCancellable","mockInputCancellable","mockPasswordCancellable","mockConfirmCancellable","mockSearchCancellable","module","select","input","password","selectCancellable","inputCancellable","passwordCancellable","confirmCancellable","searchCancellable","describe","sprinkle","beforeEach","schema","Type","Object","name","String","Sprinkle","settings","mockClear","test","callOrder","beforeShowFn","push","mockImplementation","menu","title","beforeShow","items","action","showMenu","expect","toHaveBeenCalledTimes","toBe","receivedSprinkle","mockResolvedValueOnce","s","result","SearchSelect","message","source","value","calls","sourceFn","toBeNull"],"sources":["../../../../src/Sprinkle/__tests__/enhancements.test.ts"],"sourcesContent":["import { describe, expect, test, mock, beforeEach } from \"bun:test\";\nimport { Sprinkle, Type, type IMenu } from \"../index.js\";\n\nconst mockSelect = mock();\nconst mockInput = mock();\nconst mockPassword = mock();\nconst mockSelectCancellable = mock();\nconst mockInputCancellable = mock();\nconst mockPasswordCancellable = mock();\nconst mockConfirmCancellable = mock();\nconst mockSearchCancellable = mock();\n\nmock.module(\"@inquirer/prompts\", () => ({\n select: mockSelect,\n input: mockInput,\n password: mockPassword,\n}));\n\nmock.module(\"../prompts.js\", () => ({\n selectCancellable: mockSelectCancellable,\n inputCancellable: mockInputCancellable,\n passwordCancellable: mockPasswordCancellable,\n confirmCancellable: mockConfirmCancellable,\n searchCancellable: mockSearchCancellable,\n select: mockSelectCancellable,\n}));\n\ndescribe(\"beforeShow hook (2.2)\", () => {\n let sprinkle: Sprinkle<any>;\n\n beforeEach(() => {\n const schema = Type.Object({ name: Type.String() });\n sprinkle = new Sprinkle(schema, \"/tmp/test\");\n sprinkle.settings = { name: \"test\" } as any;\n mockSelect.mockClear();\n mockSelectCancellable.mockClear();\n });\n\n test(\"calls beforeShow before rendering menu\", async () => {\n const callOrder: string[] = [];\n\n const beforeShowFn = mock(async () => {\n callOrder.push(\"beforeShow\");\n });\n\n mockSelectCancellable.mockImplementation(async () => {\n callOrder.push(\"select\");\n return -1; // exit\n });\n\n const menu: IMenu<any> = {\n title: \"Test\",\n beforeShow: beforeShowFn,\n items: [{ title: \"Action\", action: async () => {} }],\n };\n\n await sprinkle.showMenu(menu);\n\n expect(beforeShowFn).toHaveBeenCalledTimes(1);\n expect(callOrder[0]).toBe(\"beforeShow\");\n expect(callOrder[1]).toBe(\"select\");\n });\n\n test(\"passes sprinkle instance to beforeShow\", async () => {\n let receivedSprinkle: any;\n\n mockSelectCancellable.mockResolvedValueOnce(-1);\n\n const menu: IMenu<any> = {\n title: \"Test\",\n beforeShow: async (s) => {\n receivedSprinkle = s;\n },\n items: [{ title: \"Action\", action: async () => {} }],\n };\n\n await sprinkle.showMenu(menu);\n expect(receivedSprinkle).toBe(sprinkle);\n });\n\n test(\"menu works without beforeShow\", async () => {\n mockSelectCancellable.mockResolvedValueOnce(-1);\n\n const menu: IMenu<any> = {\n title: \"Test\",\n items: [{ title: \"Action\", action: async () => {} }],\n };\n\n await sprinkle.showMenu(menu);\n // Should complete without error\n });\n});\n\ndescribe(\"SearchSelect (2.3)\", () => {\n beforeEach(() => {\n mockSearchCancellable.mockClear();\n });\n\n test(\"delegates to search prompt\", async () => {\n mockSearchCancellable.mockResolvedValueOnce(\"selected-value\");\n\n const result = await Sprinkle.SearchSelect({\n message: \"Pick one\",\n source: () => [\n { name: \"Option A\", value: \"a\" },\n { name: \"Option B\", value: \"b\" },\n ],\n });\n\n expect(result).toBe(\"selected-value\");\n expect(mockSearchCancellable).toHaveBeenCalledTimes(1);\n expect(mockSearchCancellable.mock.calls[0][0].message).toBe(\"Pick one\");\n });\n\n test(\"passes source function through\", async () => {\n const sourceFn = mock(() => [{ name: \"X\", value: \"x\" }]);\n mockSearchCancellable.mockResolvedValueOnce(\"x\");\n\n await Sprinkle.SearchSelect({\n message: \"Search\",\n source: sourceFn,\n });\n\n expect(mockSearchCancellable.mock.calls[0][0].source).toBe(sourceFn);\n });\n\n test(\"returns null when cancelled\", async () => {\n mockSearchCancellable.mockResolvedValueOnce(null);\n\n const result = await Sprinkle.SearchSelect({\n message: \"Pick one\",\n source: () => [{ name: \"A\", value: \"a\" }],\n });\n\n expect(result).toBeNull();\n });\n});\n\n// Note: \"Optional type support (2.4)\" tests removed - they tested the old sequential\n// FillInStruct behavior. The new menu-based FillInStruct handles optional fields\n// differently (via menu selection). See fill-in-struct.test.ts for comprehensive tests.\n"],"mappings":";;AAAA,IAAAA,QAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AAEA,MAAME,UAAU,GAAG,IAAAC,aAAI,EAAC,CAAC;AACzB,MAAMC,SAAS,GAAG,IAAAD,aAAI,EAAC,CAAC;AACxB,MAAME,YAAY,GAAG,IAAAF,aAAI,EAAC,CAAC;AAC3B,MAAMG,qBAAqB,GAAG,IAAAH,aAAI,EAAC,CAAC;AACpC,MAAMI,oBAAoB,GAAG,IAAAJ,aAAI,EAAC,CAAC;AACnC,MAAMK,uBAAuB,GAAG,IAAAL,aAAI,EAAC,CAAC;AACtC,MAAMM,sBAAsB,GAAG,IAAAN,aAAI,EAAC,CAAC;AACrC,MAAMO,qBAAqB,GAAG,IAAAP,aAAI,EAAC,CAAC;AAEpCA,aAAI,CAACQ,MAAM,CAAC,mBAAmB,EAAE,OAAO;EACtCC,MAAM,EAAEV,UAAU;EAClBW,KAAK,EAAET,SAAS;EAChBU,QAAQ,EAAET;AACZ,CAAC,CAAC,CAAC;AAEHF,aAAI,CAACQ,MAAM,CAAC,eAAe,EAAE,OAAO;EAClCI,iBAAiB,EAAET,qBAAqB;EACxCU,gBAAgB,EAAET,oBAAoB;EACtCU,mBAAmB,EAAET,uBAAuB;EAC5CU,kBAAkB,EAAET,sBAAsB;EAC1CU,iBAAiB,EAAET,qBAAqB;EACxCE,MAAM,EAAEN;AACV,CAAC,CAAC,CAAC;AAEH,IAAAc,iBAAQ,EAAC,uBAAuB,EAAE,MAAM;EACtC,IAAIC,QAAuB;EAE3B,IAAAC,mBAAU,EAAC,MAAM;IACf,MAAMC,MAAM,GAAGC,WAAI,CAACC,MAAM,CAAC;MAAEC,IAAI,EAAEF,WAAI,CAACG,MAAM,CAAC;IAAE,CAAC,CAAC;IACnDN,QAAQ,GAAG,IAAIO,eAAQ,CAACL,MAAM,EAAE,WAAW,CAAC;IAC5CF,QAAQ,CAACQ,QAAQ,GAAG;MAAEH,IAAI,EAAE;IAAO,CAAQ;IAC3CxB,UAAU,CAAC4B,SAAS,CAAC,CAAC;IACtBxB,qBAAqB,CAACwB,SAAS,CAAC,CAAC;EACnC,CAAC,CAAC;EAEF,IAAAC,aAAI,EAAC,wCAAwC,EAAE,YAAY;IACzD,MAAMC,SAAmB,GAAG,EAAE;IAE9B,MAAMC,YAAY,GAAG,IAAA9B,aAAI,EAAC,YAAY;MACpC6B,SAAS,CAACE,IAAI,CAAC,YAAY,CAAC;IAC9B,CAAC,CAAC;IAEF5B,qBAAqB,CAAC6B,kBAAkB,CAAC,YAAY;MACnDH,SAAS,CAACE,IAAI,CAAC,QAAQ,CAAC;MACxB,OAAO,CAAC,CAAC,CAAC,CAAC;IACb,CAAC,CAAC;IAEF,MAAME,IAAgB,GAAG;MACvBC,KAAK,EAAE,MAAM;MACbC,UAAU,EAAEL,YAAY;MACxBM,KAAK,EAAE,CAAC;QAAEF,KAAK,EAAE,QAAQ;QAAEG,MAAM,EAAE,MAAAA,CAAA,KAAY,CAAC;MAAE,CAAC;IACrD,CAAC;IAED,MAAMnB,QAAQ,CAACoB,QAAQ,CAACL,IAAI,CAAC;IAE7B,IAAAM,eAAM,EAACT,YAAY,CAAC,CAACU,qBAAqB,CAAC,CAAC,CAAC;IAC7C,IAAAD,eAAM,EAACV,SAAS,CAAC,CAAC,CAAC,CAAC,CAACY,IAAI,CAAC,YAAY,CAAC;IACvC,IAAAF,eAAM,EAACV,SAAS,CAAC,CAAC,CAAC,CAAC,CAACY,IAAI,CAAC,QAAQ,CAAC;EACrC,CAAC,CAAC;EAEF,IAAAb,aAAI,EAAC,wCAAwC,EAAE,YAAY;IACzD,IAAIc,gBAAqB;IAEzBvC,qBAAqB,CAACwC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAMV,IAAgB,GAAG;MACvBC,KAAK,EAAE,MAAM;MACbC,UAAU,EAAE,MAAOS,CAAC,IAAK;QACvBF,gBAAgB,GAAGE,CAAC;MACtB,CAAC;MACDR,KAAK,EAAE,CAAC;QAAEF,KAAK,EAAE,QAAQ;QAAEG,MAAM,EAAE,MAAAA,CAAA,KAAY,CAAC;MAAE,CAAC;IACrD,CAAC;IAED,MAAMnB,QAAQ,CAACoB,QAAQ,CAACL,IAAI,CAAC;IAC7B,IAAAM,eAAM,EAACG,gBAAgB,CAAC,CAACD,IAAI,CAACvB,QAAQ,CAAC;EACzC,CAAC,CAAC;EAEF,IAAAU,aAAI,EAAC,+BAA+B,EAAE,YAAY;IAChDzB,qBAAqB,CAACwC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAMV,IAAgB,GAAG;MACvBC,KAAK,EAAE,MAAM;MACbE,KAAK,EAAE,CAAC;QAAEF,KAAK,EAAE,QAAQ;QAAEG,MAAM,EAAE,MAAAA,CAAA,KAAY,CAAC;MAAE,CAAC;IACrD,CAAC;IAED,MAAMnB,QAAQ,CAACoB,QAAQ,CAACL,IAAI,CAAC;IAC7B;EACF,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,IAAAhB,iBAAQ,EAAC,oBAAoB,EAAE,MAAM;EACnC,IAAAE,mBAAU,EAAC,MAAM;IACfZ,qBAAqB,CAACoB,SAAS,CAAC,CAAC;EACnC,CAAC,CAAC;EAEF,IAAAC,aAAI,EAAC,4BAA4B,EAAE,YAAY;IAC7CrB,qBAAqB,CAACoC,qBAAqB,CAAC,gBAAgB,CAAC;IAE7D,MAAME,MAAM,GAAG,MAAMpB,eAAQ,CAACqB,YAAY,CAAC;MACzCC,OAAO,EAAE,UAAU;MACnBC,MAAM,EAAEA,CAAA,KAAM,CACZ;QAAEzB,IAAI,EAAE,UAAU;QAAE0B,KAAK,EAAE;MAAI,CAAC,EAChC;QAAE1B,IAAI,EAAE,UAAU;QAAE0B,KAAK,EAAE;MAAI,CAAC;IAEpC,CAAC,CAAC;IAEF,IAAAV,eAAM,EAACM,MAAM,CAAC,CAACJ,IAAI,CAAC,gBAAgB,CAAC;IACrC,IAAAF,eAAM,EAAChC,qBAAqB,CAAC,CAACiC,qBAAqB,CAAC,CAAC,CAAC;IACtD,IAAAD,eAAM,EAAChC,qBAAqB,CAACP,IAAI,CAACkD,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAACH,OAAO,CAAC,CAACN,IAAI,CAAC,UAAU,CAAC;EACzE,CAAC,CAAC;EAEF,IAAAb,aAAI,EAAC,gCAAgC,EAAE,YAAY;IACjD,MAAMuB,QAAQ,GAAG,IAAAnD,aAAI,EAAC,MAAM,CAAC;MAAEuB,IAAI,EAAE,GAAG;MAAE0B,KAAK,EAAE;IAAI,CAAC,CAAC,CAAC;IACxD1C,qBAAqB,CAACoC,qBAAqB,CAAC,GAAG,CAAC;IAEhD,MAAMlB,eAAQ,CAACqB,YAAY,CAAC;MAC1BC,OAAO,EAAE,QAAQ;MACjBC,MAAM,EAAEG;IACV,CAAC,CAAC;IAEF,IAAAZ,eAAM,EAAChC,qBAAqB,CAACP,IAAI,CAACkD,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAACF,MAAM,CAAC,CAACP,IAAI,CAACU,QAAQ,CAAC;EACtE,CAAC,CAAC;EAEF,IAAAvB,aAAI,EAAC,6BAA6B,EAAE,YAAY;IAC9CrB,qBAAqB,CAACoC,qBAAqB,CAAC,IAAI,CAAC;IAEjD,MAAME,MAAM,GAAG,MAAMpB,eAAQ,CAACqB,YAAY,CAAC;MACzCC,OAAO,EAAE,UAAU;MACnBC,MAAM,EAAEA,CAAA,KAAM,CAAC;QAAEzB,IAAI,EAAE,GAAG;QAAE0B,KAAK,EAAE;MAAI,CAAC;IAC1C,CAAC,CAAC;IAEF,IAAAV,eAAM,EAACM,MAAM,CAAC,CAACO,QAAQ,CAAC,CAAC;EAC3B,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _bunTest = require("bun:test");
|
|
4
|
+
var _typebox = require("@sinclair/typebox");
|
|
5
|
+
var _fieldUtils = require("../utils/field-utils.js");
|
|
6
|
+
(0, _bunTest.describe)("isFieldRequired", () => {
|
|
7
|
+
(0, _bunTest.test)("returns true for plain required field", () => {
|
|
8
|
+
(0, _bunTest.expect)((0, _fieldUtils.isFieldRequired)(_typebox.Type.String())).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
(0, _bunTest.test)("returns false for optional field", () => {
|
|
11
|
+
(0, _bunTest.expect)((0, _fieldUtils.isFieldRequired)(_typebox.Type.Optional(_typebox.Type.String()))).toBe(false);
|
|
12
|
+
});
|
|
13
|
+
(0, _bunTest.test)("returns false for field with default", () => {
|
|
14
|
+
(0, _bunTest.expect)((0, _fieldUtils.isFieldRequired)(_typebox.Type.String({
|
|
15
|
+
default: "hello"
|
|
16
|
+
}))).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
(0, _bunTest.test)("returns true for nullable field with default", () => {
|
|
19
|
+
// Nullable fields with defaults are required because the user should
|
|
20
|
+
// explicitly choose whether to use the value or set null
|
|
21
|
+
const schema = _typebox.Type.Union([_typebox.Type.String({
|
|
22
|
+
default: "hello"
|
|
23
|
+
}), _typebox.Type.Null()]);
|
|
24
|
+
(0, _bunTest.expect)((0, _fieldUtils.isFieldRequired)(schema)).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
(0, _bunTest.describe)("countRequiredFields", () => {
|
|
28
|
+
(0, _bunTest.test)("counts fields in simple object", () => {
|
|
29
|
+
const schema = _typebox.Type.Object({
|
|
30
|
+
name: _typebox.Type.String(),
|
|
31
|
+
age: _typebox.Type.BigInt()
|
|
32
|
+
});
|
|
33
|
+
const state = new Map();
|
|
34
|
+
const result = (0, _fieldUtils.countRequiredFields)(schema, state);
|
|
35
|
+
(0, _bunTest.expect)(result.total).toBe(2);
|
|
36
|
+
(0, _bunTest.expect)(result.filled).toBe(0);
|
|
37
|
+
});
|
|
38
|
+
(0, _bunTest.test)("skips optional fields", () => {
|
|
39
|
+
const schema = _typebox.Type.Object({
|
|
40
|
+
name: _typebox.Type.String(),
|
|
41
|
+
nickname: _typebox.Type.Optional(_typebox.Type.String())
|
|
42
|
+
});
|
|
43
|
+
const state = new Map();
|
|
44
|
+
const result = (0, _fieldUtils.countRequiredFields)(schema, state);
|
|
45
|
+
(0, _bunTest.expect)(result.total).toBe(1);
|
|
46
|
+
});
|
|
47
|
+
(0, _bunTest.test)("skips fields with defaults", () => {
|
|
48
|
+
const schema = _typebox.Type.Object({
|
|
49
|
+
name: _typebox.Type.String(),
|
|
50
|
+
timeout: _typebox.Type.BigInt({
|
|
51
|
+
default: 30n
|
|
52
|
+
})
|
|
53
|
+
});
|
|
54
|
+
const state = new Map();
|
|
55
|
+
const result = (0, _fieldUtils.countRequiredFields)(schema, state);
|
|
56
|
+
(0, _bunTest.expect)(result.total).toBe(1);
|
|
57
|
+
});
|
|
58
|
+
(0, _bunTest.test)("counts filled fields", () => {
|
|
59
|
+
const schema = _typebox.Type.Object({
|
|
60
|
+
name: _typebox.Type.String(),
|
|
61
|
+
age: _typebox.Type.BigInt()
|
|
62
|
+
});
|
|
63
|
+
const state = new Map([["name", {
|
|
64
|
+
status: "set",
|
|
65
|
+
value: "Alice"
|
|
66
|
+
}]]);
|
|
67
|
+
const result = (0, _fieldUtils.countRequiredFields)(schema, state);
|
|
68
|
+
(0, _bunTest.expect)(result.total).toBe(2);
|
|
69
|
+
(0, _bunTest.expect)(result.filled).toBe(1);
|
|
70
|
+
});
|
|
71
|
+
(0, _bunTest.test)("counts null as filled for nullable fields", () => {
|
|
72
|
+
const schema = _typebox.Type.Object({
|
|
73
|
+
name: _typebox.Type.Union([_typebox.Type.String(), _typebox.Type.Null()])
|
|
74
|
+
});
|
|
75
|
+
const state = new Map([["name", {
|
|
76
|
+
status: "null"
|
|
77
|
+
}]]);
|
|
78
|
+
const result = (0, _fieldUtils.countRequiredFields)(schema, state);
|
|
79
|
+
(0, _bunTest.expect)(result.filled).toBe(1);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
(0, _bunTest.describe)("buildFieldLabel", () => {
|
|
83
|
+
(0, _bunTest.test)("shows [not set] with asterisk for required unset field", () => {
|
|
84
|
+
const label = (0, _fieldUtils.buildFieldLabel)("name", _typebox.Type.String(), {
|
|
85
|
+
status: "unset"
|
|
86
|
+
});
|
|
87
|
+
(0, _bunTest.expect)(label).toContain("name");
|
|
88
|
+
(0, _bunTest.expect)(label).toContain("[not set]");
|
|
89
|
+
(0, _bunTest.expect)(label).toContain("*");
|
|
90
|
+
});
|
|
91
|
+
(0, _bunTest.test)("shows [not set] without asterisk for optional field", () => {
|
|
92
|
+
const label = (0, _fieldUtils.buildFieldLabel)("nickname", _typebox.Type.Optional(_typebox.Type.String()), {
|
|
93
|
+
status: "unset"
|
|
94
|
+
});
|
|
95
|
+
(0, _bunTest.expect)(label).toContain("[not set]");
|
|
96
|
+
(0, _bunTest.expect)(label).not.toContain("*");
|
|
97
|
+
});
|
|
98
|
+
(0, _bunTest.test)("shows default value for unset field with default", () => {
|
|
99
|
+
const label = (0, _fieldUtils.buildFieldLabel)("timeout", _typebox.Type.BigInt({
|
|
100
|
+
default: 30n
|
|
101
|
+
}), {
|
|
102
|
+
status: "unset"
|
|
103
|
+
});
|
|
104
|
+
(0, _bunTest.expect)(label).toContain("default");
|
|
105
|
+
(0, _bunTest.expect)(label).toContain("30");
|
|
106
|
+
});
|
|
107
|
+
(0, _bunTest.test)("shows null for null state", () => {
|
|
108
|
+
const label = (0, _fieldUtils.buildFieldLabel)("value", _typebox.Type.Union([_typebox.Type.String(), _typebox.Type.Null()]), {
|
|
109
|
+
status: "null"
|
|
110
|
+
});
|
|
111
|
+
(0, _bunTest.expect)(label).toContain("null");
|
|
112
|
+
});
|
|
113
|
+
(0, _bunTest.test)("shows value preview for set field", () => {
|
|
114
|
+
const label = (0, _fieldUtils.buildFieldLabel)("name", _typebox.Type.String(), {
|
|
115
|
+
status: "set",
|
|
116
|
+
value: "Alice"
|
|
117
|
+
});
|
|
118
|
+
(0, _bunTest.expect)(label).toContain("Alice");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
(0, _bunTest.describe)("getInitialFieldState", () => {
|
|
122
|
+
(0, _bunTest.test)("returns unset for undefined", () => {
|
|
123
|
+
(0, _bunTest.expect)((0, _fieldUtils.getInitialFieldState)(_typebox.Type.String(), undefined)).toEqual({
|
|
124
|
+
status: "unset"
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
(0, _bunTest.test)("returns null for null value", () => {
|
|
128
|
+
(0, _bunTest.expect)((0, _fieldUtils.getInitialFieldState)(_typebox.Type.String(), null)).toEqual({
|
|
129
|
+
status: "null"
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
(0, _bunTest.test)("returns set with value", () => {
|
|
133
|
+
(0, _bunTest.expect)((0, _fieldUtils.getInitialFieldState)(_typebox.Type.String(), "hello")).toEqual({
|
|
134
|
+
status: "set",
|
|
135
|
+
value: "hello"
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
(0, _bunTest.describe)("allRequiredFieldsFilled", () => {
|
|
140
|
+
(0, _bunTest.test)("returns true when all required fields filled", () => {
|
|
141
|
+
const schema = _typebox.Type.Object({
|
|
142
|
+
name: _typebox.Type.String(),
|
|
143
|
+
nickname: _typebox.Type.Optional(_typebox.Type.String())
|
|
144
|
+
});
|
|
145
|
+
const state = new Map([["name", {
|
|
146
|
+
status: "set",
|
|
147
|
+
value: "Alice"
|
|
148
|
+
}]]);
|
|
149
|
+
(0, _bunTest.expect)((0, _fieldUtils.allRequiredFieldsFilled)(schema, state)).toBe(true);
|
|
150
|
+
});
|
|
151
|
+
(0, _bunTest.test)("returns false when required field missing", () => {
|
|
152
|
+
const schema = _typebox.Type.Object({
|
|
153
|
+
name: _typebox.Type.String(),
|
|
154
|
+
age: _typebox.Type.BigInt()
|
|
155
|
+
});
|
|
156
|
+
const state = new Map([["name", {
|
|
157
|
+
status: "set",
|
|
158
|
+
value: "Alice"
|
|
159
|
+
}]]);
|
|
160
|
+
(0, _bunTest.expect)((0, _fieldUtils.allRequiredFieldsFilled)(schema, state)).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
(0, _bunTest.test)("returns true for all-optional schema", () => {
|
|
163
|
+
const schema = _typebox.Type.Object({
|
|
164
|
+
nickname: _typebox.Type.Optional(_typebox.Type.String())
|
|
165
|
+
});
|
|
166
|
+
const state = new Map();
|
|
167
|
+
(0, _bunTest.expect)((0, _fieldUtils.allRequiredFieldsFilled)(schema, state)).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=field-utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-utils.test.js","names":["_bunTest","require","_typebox","_fieldUtils","describe","test","expect","isFieldRequired","Type","String","toBe","Optional","default","schema","Union","Null","Object","name","age","BigInt","state","Map","result","countRequiredFields","total","filled","nickname","timeout","status","value","label","buildFieldLabel","toContain","not","getInitialFieldState","undefined","toEqual","allRequiredFieldsFilled"],"sources":["../../../../src/Sprinkle/__tests__/field-utils.test.ts"],"sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport { Type } from \"@sinclair/typebox\";\nimport {\n countRequiredFields,\n isFieldRequired,\n buildFieldLabel,\n getInitialFieldState,\n allRequiredFieldsFilled,\n} from \"../utils/field-utils.js\";\nimport type { FieldState } from \"../types.js\";\n\ndescribe(\"isFieldRequired\", () => {\n test(\"returns true for plain required field\", () => {\n expect(isFieldRequired(Type.String())).toBe(true);\n });\n\n test(\"returns false for optional field\", () => {\n expect(isFieldRequired(Type.Optional(Type.String()))).toBe(false);\n });\n\n test(\"returns false for field with default\", () => {\n expect(isFieldRequired(Type.String({ default: \"hello\" }))).toBe(false);\n });\n\n test(\"returns true for nullable field with default\", () => {\n // Nullable fields with defaults are required because the user should\n // explicitly choose whether to use the value or set null\n const schema = Type.Union([Type.String({ default: \"hello\" }), Type.Null()]);\n expect(isFieldRequired(schema)).toBe(true);\n });\n});\n\ndescribe(\"countRequiredFields\", () => {\n test(\"counts fields in simple object\", () => {\n const schema = Type.Object({\n name: Type.String(),\n age: Type.BigInt(),\n });\n const state = new Map<string, FieldState>();\n\n const result = countRequiredFields(schema, state);\n expect(result.total).toBe(2);\n expect(result.filled).toBe(0);\n });\n\n test(\"skips optional fields\", () => {\n const schema = Type.Object({\n name: Type.String(),\n nickname: Type.Optional(Type.String()),\n });\n const state = new Map<string, FieldState>();\n\n const result = countRequiredFields(schema, state);\n expect(result.total).toBe(1);\n });\n\n test(\"skips fields with defaults\", () => {\n const schema = Type.Object({\n name: Type.String(),\n timeout: Type.BigInt({ default: 30n }),\n });\n const state = new Map<string, FieldState>();\n\n const result = countRequiredFields(schema, state);\n expect(result.total).toBe(1);\n });\n\n test(\"counts filled fields\", () => {\n const schema = Type.Object({\n name: Type.String(),\n age: Type.BigInt(),\n });\n const state = new Map<string, FieldState>([\n [\"name\", { status: \"set\", value: \"Alice\" }],\n ]);\n\n const result = countRequiredFields(schema, state);\n expect(result.total).toBe(2);\n expect(result.filled).toBe(1);\n });\n\n test(\"counts null as filled for nullable fields\", () => {\n const schema = Type.Object({\n name: Type.Union([Type.String(), Type.Null()]),\n });\n const state = new Map<string, FieldState>([[\"name\", { status: \"null\" }]]);\n\n const result = countRequiredFields(schema, state);\n expect(result.filled).toBe(1);\n });\n});\n\ndescribe(\"buildFieldLabel\", () => {\n test(\"shows [not set] with asterisk for required unset field\", () => {\n const label = buildFieldLabel(\"name\", Type.String(), { status: \"unset\" });\n expect(label).toContain(\"name\");\n expect(label).toContain(\"[not set]\");\n expect(label).toContain(\"*\");\n });\n\n test(\"shows [not set] without asterisk for optional field\", () => {\n const label = buildFieldLabel(\"nickname\", Type.Optional(Type.String()), {\n status: \"unset\",\n });\n expect(label).toContain(\"[not set]\");\n expect(label).not.toContain(\"*\");\n });\n\n test(\"shows default value for unset field with default\", () => {\n const label = buildFieldLabel(\n \"timeout\",\n Type.BigInt({ default: 30n }),\n { status: \"unset\" },\n );\n expect(label).toContain(\"default\");\n expect(label).toContain(\"30\");\n });\n\n test(\"shows null for null state\", () => {\n const label = buildFieldLabel(\n \"value\",\n Type.Union([Type.String(), Type.Null()]),\n { status: \"null\" },\n );\n expect(label).toContain(\"null\");\n });\n\n test(\"shows value preview for set field\", () => {\n const label = buildFieldLabel(\"name\", Type.String(), {\n status: \"set\",\n value: \"Alice\",\n });\n expect(label).toContain(\"Alice\");\n });\n});\n\ndescribe(\"getInitialFieldState\", () => {\n test(\"returns unset for undefined\", () => {\n expect(getInitialFieldState(Type.String(), undefined)).toEqual({\n status: \"unset\",\n });\n });\n\n test(\"returns null for null value\", () => {\n expect(getInitialFieldState(Type.String(), null)).toEqual({\n status: \"null\",\n });\n });\n\n test(\"returns set with value\", () => {\n expect(getInitialFieldState(Type.String(), \"hello\")).toEqual({\n status: \"set\",\n value: \"hello\",\n });\n });\n});\n\ndescribe(\"allRequiredFieldsFilled\", () => {\n test(\"returns true when all required fields filled\", () => {\n const schema = Type.Object({\n name: Type.String(),\n nickname: Type.Optional(Type.String()),\n });\n const state = new Map<string, FieldState>([\n [\"name\", { status: \"set\", value: \"Alice\" }],\n ]);\n\n expect(allRequiredFieldsFilled(schema, state)).toBe(true);\n });\n\n test(\"returns false when required field missing\", () => {\n const schema = Type.Object({\n name: Type.String(),\n age: Type.BigInt(),\n });\n const state = new Map<string, FieldState>([\n [\"name\", { status: \"set\", value: \"Alice\" }],\n ]);\n\n expect(allRequiredFieldsFilled(schema, state)).toBe(false);\n });\n\n test(\"returns true for all-optional schema\", () => {\n const schema = Type.Object({\n nickname: Type.Optional(Type.String()),\n });\n const state = new Map<string, FieldState>();\n\n expect(allRequiredFieldsFilled(schema, state)).toBe(true);\n });\n});\n"],"mappings":"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","ignoreList":[]}
|