|
1 | 1 | import { describe, expect, test } from "bun:test" |
2 | | -import { Schema, SchemaGetter } from "effect" |
| 2 | +import { Effect, Schema, SchemaGetter } from "effect" |
3 | 3 | import z from "zod" |
4 | 4 |
|
5 | 5 | import { zod, ZodOverride } from "../../src/util/effect-zod" |
@@ -669,4 +669,89 @@ describe("util.effect-zod", () => { |
669 | 669 | expect(shape.properties.port.exclusiveMinimum).toBe(0) |
670 | 670 | }) |
671 | 671 | }) |
| 672 | + |
| 673 | + describe("Schema.optionalWith defaults", () => { |
| 674 | + test("parsing undefined returns the default value", () => { |
| 675 | + const schema = zod( |
| 676 | + Schema.Struct({ |
| 677 | + mode: Schema.String.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed("ctrl-x"))), |
| 678 | + }), |
| 679 | + ) |
| 680 | + expect(schema.parse({})).toEqual({ mode: "ctrl-x" }) |
| 681 | + expect(schema.parse({ mode: undefined })).toEqual({ mode: "ctrl-x" }) |
| 682 | + }) |
| 683 | + |
| 684 | + test("parsing a real value returns that value (default does not fire)", () => { |
| 685 | + const schema = zod( |
| 686 | + Schema.Struct({ |
| 687 | + mode: Schema.String.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed("ctrl-x"))), |
| 688 | + }), |
| 689 | + ) |
| 690 | + expect(schema.parse({ mode: "ctrl-y" })).toEqual({ mode: "ctrl-y" }) |
| 691 | + }) |
| 692 | + |
| 693 | + test("default on a number field", () => { |
| 694 | + const schema = zod( |
| 695 | + Schema.Struct({ |
| 696 | + count: Schema.Number.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed(42))), |
| 697 | + }), |
| 698 | + ) |
| 699 | + expect(schema.parse({})).toEqual({ count: 42 }) |
| 700 | + expect(schema.parse({ count: 7 })).toEqual({ count: 7 }) |
| 701 | + }) |
| 702 | + |
| 703 | + test("multiple defaulted fields inside a struct", () => { |
| 704 | + const schema = zod( |
| 705 | + Schema.Struct({ |
| 706 | + leader: Schema.String.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed("ctrl-x"))), |
| 707 | + quit: Schema.String.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed("ctrl-c"))), |
| 708 | + inner: Schema.String, |
| 709 | + }), |
| 710 | + ) |
| 711 | + expect(schema.parse({ inner: "hi" })).toEqual({ |
| 712 | + leader: "ctrl-x", |
| 713 | + quit: "ctrl-c", |
| 714 | + inner: "hi", |
| 715 | + }) |
| 716 | + expect(schema.parse({ leader: "a", quit: "b", inner: "c" })).toEqual({ |
| 717 | + leader: "a", |
| 718 | + quit: "b", |
| 719 | + inner: "c", |
| 720 | + }) |
| 721 | + }) |
| 722 | + |
| 723 | + test("JSON Schema output includes the default key", () => { |
| 724 | + const schema = zod( |
| 725 | + Schema.Struct({ |
| 726 | + mode: Schema.String.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed("ctrl-x"))), |
| 727 | + }), |
| 728 | + ) |
| 729 | + const shape = json(schema) as any |
| 730 | + expect(shape.properties.mode.default).toBe("ctrl-x") |
| 731 | + }) |
| 732 | + |
| 733 | + test("default referencing a computed value resolves when evaluated", () => { |
| 734 | + // Simulates `keybinds.ts` style of per-platform defaults: the default is |
| 735 | + // produced by an Effect that computes a value at decode time. |
| 736 | + const platform = "darwin" |
| 737 | + const fallback = platform === "darwin" ? "cmd-k" : "ctrl-k" |
| 738 | + const schema = zod( |
| 739 | + Schema.Struct({ |
| 740 | + command_palette: Schema.String.pipe( |
| 741 | + Schema.optional, |
| 742 | + Schema.withDecodingDefault(Effect.sync(() => fallback)), |
| 743 | + ), |
| 744 | + }), |
| 745 | + ) |
| 746 | + expect(schema.parse({})).toEqual({ command_palette: "cmd-k" }) |
| 747 | + const shape = json(schema) as any |
| 748 | + expect(shape.properties.command_palette.default).toBe("cmd-k") |
| 749 | + }) |
| 750 | + |
| 751 | + test("plain Schema.optional (no default) still emits .optional() (regression)", () => { |
| 752 | + const schema = zod(Schema.Struct({ foo: Schema.optional(Schema.String) })) |
| 753 | + expect(schema.parse({})).toEqual({}) |
| 754 | + expect(schema.parse({ foo: "hi" })).toEqual({ foo: "hi" }) |
| 755 | + }) |
| 756 | + }) |
672 | 757 | }) |
0 commit comments