@@ -1818,4 +1818,170 @@ describe('anyOf', () => {
1818
1818
expect ( selects ) . to . have . length . of ( 0 ) ;
1819
1819
} ) ;
1820
1820
} ) ;
1821
+
1822
+ describe ( 'Boolean field value preservation' , ( ) => {
1823
+ it ( 'should preserve boolean values when switching between anyOf options with shared properties' , ( ) => {
1824
+ const schema = {
1825
+ type : 'object' ,
1826
+ properties : {
1827
+ items : {
1828
+ type : 'array' ,
1829
+ items : {
1830
+ type : 'object' ,
1831
+ anyOf : [
1832
+ {
1833
+ title : 'Type A' ,
1834
+ properties : {
1835
+ type : { type : 'string' , enum : [ 'typeA' ] , default : 'typeA' } ,
1836
+ showField : { type : 'boolean' } ,
1837
+ } ,
1838
+ } ,
1839
+ {
1840
+ title : 'Type B' ,
1841
+ properties : {
1842
+ type : { type : 'string' , enum : [ 'typeB' ] , default : 'typeB' } ,
1843
+ showField : { type : 'boolean' } ,
1844
+ } ,
1845
+ } ,
1846
+ ] ,
1847
+ } ,
1848
+ } ,
1849
+ } ,
1850
+ } ;
1851
+
1852
+ const { node, onChange } = createFormComponent ( {
1853
+ schema,
1854
+ formData : {
1855
+ items : [ { type : 'typeA' , showField : true } ] ,
1856
+ } ,
1857
+ experimental_defaultFormStateBehavior : {
1858
+ mergeDefaultsIntoFormData : 'useDefaultIfFormDataUndefined' ,
1859
+ } ,
1860
+ } ) ;
1861
+
1862
+ // Wait for initial form setup to complete
1863
+ if ( onChange . lastCall ) {
1864
+ // Initial state - should have showField = true
1865
+ let lastFormData = onChange . lastCall . args [ 0 ] . formData ;
1866
+ expect ( lastFormData . items [ 0 ] . showField ) . to . equal ( true ) ;
1867
+ }
1868
+
1869
+ // Switch to typeB
1870
+ const dropdown = node . querySelector ( 'select[id="root_items_0__anyof_select"]' ) ;
1871
+ if ( dropdown ) {
1872
+ act ( ( ) => {
1873
+ fireEvent . change ( dropdown , { target : { value : '1' } } ) ;
1874
+ } ) ;
1875
+
1876
+ // After switching, the boolean value should be preserved, not converted to {}
1877
+ if ( onChange . lastCall ) {
1878
+ const lastFormData = onChange . lastCall . args [ 0 ] . formData ;
1879
+ expect ( lastFormData . items [ 0 ] . type ) . to . equal ( 'typeB' ) ;
1880
+ expect ( lastFormData . items [ 0 ] . showField ) . to . equal ( true ) ; // Should still be true, not {}
1881
+ }
1882
+ }
1883
+ } ) ;
1884
+
1885
+ it ( 'should handle undefined boolean fields correctly when switching anyOf options' , ( ) => {
1886
+ const schema = {
1887
+ type : 'object' ,
1888
+ properties : {
1889
+ items : {
1890
+ type : 'array' ,
1891
+ items : {
1892
+ type : 'object' ,
1893
+ anyOf : [
1894
+ {
1895
+ title : 'Type A' ,
1896
+ properties : {
1897
+ type : { type : 'string' , enum : [ 'typeA' ] , default : 'typeA' } ,
1898
+ showField : { type : 'boolean' } ,
1899
+ } ,
1900
+ } ,
1901
+ {
1902
+ title : 'Type B' ,
1903
+ properties : {
1904
+ type : { type : 'string' , enum : [ 'typeB' ] , default : 'typeB' } ,
1905
+ showField : { type : 'boolean' } ,
1906
+ } ,
1907
+ } ,
1908
+ ] ,
1909
+ } ,
1910
+ } ,
1911
+ } ,
1912
+ } ;
1913
+
1914
+ const { node, onChange } = createFormComponent ( {
1915
+ schema,
1916
+ formData : {
1917
+ items : [ { type : 'typeA' } ] , // No showField defined
1918
+ } ,
1919
+ experimental_defaultFormStateBehavior : {
1920
+ mergeDefaultsIntoFormData : 'useDefaultIfFormDataUndefined' ,
1921
+ } ,
1922
+ } ) ;
1923
+
1924
+ // Switch to typeB
1925
+ const dropdown = node . querySelector ( 'select[id="root_items_0__anyof_select"]' ) ;
1926
+ if ( dropdown ) {
1927
+ act ( ( ) => {
1928
+ fireEvent . change ( dropdown , { target : { value : '1' } } ) ;
1929
+ } ) ;
1930
+
1931
+ // After switching, undefined boolean should remain undefined, not become {}
1932
+ const lastFormData = onChange . lastCall . args [ 0 ] . formData ;
1933
+ expect ( lastFormData . items [ 0 ] . type ) . to . equal ( 'typeB' ) ;
1934
+
1935
+ // showField should be undefined, not {} (the bug we fixed)
1936
+ if ( 'showField' in lastFormData . items [ 0 ] ) {
1937
+ expect ( lastFormData . items [ 0 ] . showField ) . to . not . deep . equal ( { } ) ;
1938
+ }
1939
+ }
1940
+ } ) ;
1941
+
1942
+ it ( 'should handle boolean field values correctly in direct anyOf schemas' , ( ) => {
1943
+ const schema = {
1944
+ type : 'object' ,
1945
+ anyOf : [
1946
+ {
1947
+ title : 'Option A' ,
1948
+ properties : {
1949
+ type : { type : 'string' , enum : [ 'optionA' ] , default : 'optionA' } ,
1950
+ enabled : { type : 'boolean' } ,
1951
+ } ,
1952
+ } ,
1953
+ {
1954
+ title : 'Option B' ,
1955
+ properties : {
1956
+ type : { type : 'string' , enum : [ 'optionB' ] , default : 'optionB' } ,
1957
+ enabled : { type : 'boolean' } ,
1958
+ } ,
1959
+ } ,
1960
+ ] ,
1961
+ } ;
1962
+
1963
+ const { node, onChange } = createFormComponent ( {
1964
+ schema,
1965
+ formData : { type : 'optionA' , enabled : false } ,
1966
+ experimental_defaultFormStateBehavior : {
1967
+ mergeDefaultsIntoFormData : 'useDefaultIfFormDataUndefined' ,
1968
+ } ,
1969
+ } ) ;
1970
+
1971
+ // Switch to optionB
1972
+ const dropdown = node . querySelector ( 'select[id="root__anyof_select"]' ) ;
1973
+ if ( dropdown ) {
1974
+ act ( ( ) => {
1975
+ fireEvent . change ( dropdown , { target : { value : '1' } } ) ;
1976
+ } ) ;
1977
+
1978
+ // After switching, the boolean value should be preserved, not converted to {}
1979
+ if ( onChange . lastCall ) {
1980
+ const lastFormData = onChange . lastCall . args [ 0 ] . formData ;
1981
+ expect ( lastFormData . type ) . to . equal ( 'optionB' ) ;
1982
+ expect ( lastFormData . enabled ) . to . equal ( false ) ; // Should still be false, not {}
1983
+ }
1984
+ }
1985
+ } ) ;
1986
+ } ) ;
1821
1987
} ) ;
0 commit comments