Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
jessekelly881 committed May 25, 2024
1 parent 7ecc10f commit 77a762d
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 21 deletions.
40 changes: 35 additions & 5 deletions packages/effect-form-adapter/src/tests/FieldApi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { describe, expect, it } from 'vitest'

import { FieldApi, FormApi } from '@tanstack/form-core'
import { effectValidator } from '../validator'
import { asyncSchema, schema, sleep } from './utils'
import { createValidator, effectValidator } from '../validator'
import {
asyncSchema,
ctxLayer,
schema,
schemaWithContext,
sleep,
} from './utils'

describe('field api', () => {
it('should run an onChange with Schema.minLength validation', () => {
Expand Down Expand Up @@ -79,14 +85,38 @@ describe('field api', () => {
expect(field.getMeta().errors).toEqual([])
field.setValue('a', { touch: true })
await sleep(30)
expect(field.getMeta().errors).toEqual([
'You must have a length of at least 3',
])
expect(field.getMeta().errors).toEqual(['async schema error'])
field.setValue('asdf', { touch: true })
await sleep(30)
expect(field.getMeta().errors).toEqual([])
})

it('Effect error message w/ context', async () => {
const customValidator = createValidator(ctxLayer)

const form = new FormApi({
defaultValues: {
name: '',
},
})

const field = new FieldApi({
form,
validatorAdapter: customValidator,
name: 'name',
validators: {
onChange: schemaWithContext,
},
})

field.mount()

expect(field.getMeta().errors).toEqual([])
field.setValue('a', { touch: true })
await sleep(30)
expect(field.getMeta().errors).toEqual(['ctx-123'])
})

it('should run an onChangeAsyc fn with validation option enabled', async () => {
const form = new FormApi({
defaultValues: {
Expand Down
40 changes: 32 additions & 8 deletions packages/effect-form-adapter/src/tests/utils.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,47 @@
import { Context, Effect, Layer } from 'effect'
import { Context, Effect, Layer, Option } from 'effect'
import { Schema } from '@effect/schema'
import * as ParseResult from '@effect/schema/ParseResult'

export class Ctx extends Context.Tag('Ctx')<Ctx, string>() {}
export const ctx = Layer.succeed(Ctx, Ctx.of('ctx-123'))
export const ctxLayer = Layer.succeed(Ctx, Ctx.of('ctx-123'))

export const schema = Schema.String.pipe(
Schema.minLength(3, {
message: () => 'You must have a length of at least 3',
}),
)

export const schemaWithContext = Schema.transformOrFail(schema, schema, {
decode: () => Effect.flatMap(Ctx, (c) => Effect.succeed(c)),
encode: (value) => Effect.succeed(value),
const delay = Effect.delay('10 millis')
export const asyncSchema = Schema.transformOrFail(
Schema.String,
Schema.String,
{
decode: (value, _, ast) =>
delay(
value.length >= 3
? Effect.succeed(value)
: Effect.fail(new ParseResult.Type(ast, value, 'inner msg')),
),
encode: (value) => Effect.succeed(value).pipe(delay),
},
).annotations({
message: () => delay(Effect.succeed('async schema error')),
})

export const asyncSchema = Schema.transformOrFail(schema, schema, {
decode: (value) => Effect.succeed(value).pipe(Effect.delay('10 millis')),
encode: (value) => Effect.succeed(value).pipe(Effect.delay('10 millis')),
export const schemaWithContext = Schema.transformOrFail(
Schema.String,
Schema.String,
{
decode: (_, value, ast) =>
Effect.fail(new ParseResult.Type(ast, value, '')),
encode: (value) => Effect.succeed(value),
},
).annotations({
message: () =>
Effect.map(
Effect.serviceOption(Ctx),
Option.getOrElse(() => 'no context'),
),
})

export function sleep(timeout: number): Promise<void> {
Expand Down
17 changes: 9 additions & 8 deletions packages/effect-form-adapter/src/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ export const createValidator = <R>(layer: Layer.Layer<R>) => {
const validator: Validator<unknown, Schema.Schema<any, any, R>> = () => ({
validate(
{ value }: { value: unknown },
schema: Schema.Schema<any, any>,
schema: Schema.Schema<any, any, R>,
): ValidationError {
const result = Schema.decodeUnknownEither(schema)(value)
if (Either.isLeft(result)) {
return ArrayFormatter.formatErrorSync(result.left)
.map((e) => e.message)
.join(', ') // must be joined into 1 string
}
return
const exit = runtime.runSyncExit(
Schema.decodeUnknown(schema)(value).pipe(
Effect.flip,
Effect.flatMap(ArrayFormatter.formatError),
Effect.map((es) => es.map((e) => e.message).join(', ')),
),
)
return Exit.getOrElse(exit, () => undefined)
},
async validateAsync(
{ value }: { value: unknown },
Expand Down

0 comments on commit 77a762d

Please sign in to comment.