1+ //
2+ // ContextualFormTests.swift
3+ // FormHookTests
4+ //
5+ // Created by Claude on 28/09/2025.
6+ //
7+
8+ import Foundation
9+ import SwiftUI
10+ import Quick
11+ import Nimble
12+ @preconcurrency @testable import FormHook
13+
14+ enum TestContextFieldName : Hashable {
15+ case username
16+ case email
17+ case password
18+ }
19+
20+ final class ContextualFormTests : QuickSpec {
21+ override func spec( ) {
22+ contextualFormTypeSpecs ( )
23+ }
24+
25+ func contextualFormTypeSpecs( ) {
26+ describe ( " ContextualForm " ) {
27+ context ( " type definitions " ) {
28+ it ( " has the correct structure " ) {
29+ // Just test that the type exists and can be referenced
30+ let _: ContextualForm < Text , TestContextFieldName > . Type = ContextualForm < Text , TestContextFieldName > . self
31+ expect ( true ) == true
32+ }
33+
34+ it ( " supports different content types " ) {
35+ // Test generic type constraints work
36+ let _: ContextualForm < VStack < Text > , TestContextFieldName > . Type = ContextualForm < VStack < Text > , TestContextFieldName > . self
37+ let _: ContextualForm < AnyView , TestContextFieldName > . Type = ContextualForm < AnyView , TestContextFieldName > . self
38+ expect ( true ) == true
39+ }
40+
41+ it ( " enforces Hashable constraint on FieldName " ) {
42+ // This test ensures that the FieldName generic is properly constrained
43+ // If TestContextFieldName didn't conform to Hashable, this wouldn't compile
44+ let _: ContextualForm < Text , TestContextFieldName > . Type = ContextualForm < Text , TestContextFieldName > . self
45+ expect ( true ) == true
46+ }
47+ }
48+
49+ context ( " integration with form types " ) {
50+ it ( " works with FormControl type " ) {
51+ // Test that FormControl and ContextualForm use compatible types
52+ var formState = FormState < TestContextFieldName > ( )
53+ let options = FormOption < TestContextFieldName > (
54+ mode: . onSubmit,
55+ reValidateMode: . onChange,
56+ resolver: nil ,
57+ context: nil ,
58+ shouldUnregister: true ,
59+ shouldFocusError: true ,
60+ delayErrorInNanoseconds: 0 ,
61+ onFocusField: { _ in }
62+ )
63+ let formControl = FormControl ( options: options, formState: . init(
64+ get: { formState } ,
65+ set: { formState = $0 }
66+ ) )
67+
68+ // Test that FormControl can work with the same field type
69+ _ = formControl. register ( name: TestContextFieldName . username, options: . init(
70+ rules: NoopValidator < String > ( ) ,
71+ defaultValue: " test "
72+ ) )
73+
74+ expect ( formControl. instantFormState. formValues [ . username] as? String ) == " test "
75+ }
76+
77+ it ( " supports resolver functions " ) {
78+ func testResolver(
79+ values: FormValue < TestContextFieldName > ,
80+ context: Any ? ,
81+ fieldNames: [ TestContextFieldName ]
82+ ) async -> Result < FormValue < TestContextFieldName > , FormError < TestContextFieldName > > {
83+ return . success( values)
84+ }
85+
86+ // Test that resolver type is compatible
87+ let _: Resolver < TestContextFieldName > = testResolver
88+ expect ( true ) == true
89+ }
90+ }
91+
92+ context ( " error handling types " ) {
93+ it ( " works with FormError " ) {
94+ let error = FormError < TestContextFieldName > (
95+ errorFields: [ . username] ,
96+ messages: [ . username: [ " Test error " ] ]
97+ )
98+
99+ expect ( error. errorFields. contains ( . username) ) == true
100+ expect ( error [ . username] ) == [ " Test error " ]
101+ }
102+
103+ it ( " supports FormValue operations " ) {
104+ var formValue : FormValue < TestContextFieldName > = [ : ]
105+ formValue [ . username] = " test "
106+ formValue [ . email] = " test@example.com "
107+
108+ expect ( formValue [ . username] as? String ) == " test "
109+ expect ( formValue [ . email] as? String ) == " test@example.com "
110+ }
111+ }
112+ }
113+ }
114+ }
0 commit comments