@@ -1441,3 +1441,330 @@ describe('React Form Simple - 完整测试套件', () => {
14411441 } ) ;
14421442 } ) ;
14431443} ) ;
1444+
1445+ describe . concurrent ( 'dymic form' , ( ) => {
1446+ test ( 'add' , async ( { expect } ) => {
1447+ const TestDemo = React . forwardRef ( ( props , ref ) => {
1448+ const { render, model, forceUpdate } = useForm < {
1449+ list : Array < { uid : string ; value : string } > ;
1450+ } > ( { list : [ ] } ) ;
1451+ const renderMapList = model . list . map ( ( v , index ) => {
1452+ return (
1453+ < div key = { v . uid } id = { v . uid } >
1454+ { render ( `list.${ index } .value` ) (
1455+ < input id = { `dymic-${ index } -input` } /> ,
1456+ ) }
1457+ </ div >
1458+ ) ;
1459+ } ) ;
1460+ const renderButton = (
1461+ < button
1462+ id = "dymic-add-button"
1463+ onClick = { ( ) => {
1464+ model . list . push ( {
1465+ uid : getUuid ( ) ,
1466+ value : `${ model . list . length } ` ,
1467+ } ) ;
1468+ forceUpdate ( ) ;
1469+ } }
1470+ >
1471+ add
1472+ </ button >
1473+ ) ;
1474+ useImperativeHandle ( ref , ( ) => ( { } ) ) ;
1475+ return (
1476+ < >
1477+ < div id = "add-dymic-wrap" > { renderMapList } </ div >
1478+ { renderButton }
1479+ </ >
1480+ ) ;
1481+ } ) ;
1482+ const { container } = testRender ( < TestDemo /> ) ;
1483+ const button = container . querySelector (
1484+ '#dymic-add-button' ,
1485+ ) as HTMLButtonElement ;
1486+ button . click ( ) ;
1487+ await vi . waitFor (
1488+ ( ) => {
1489+ const wrap = container . querySelector (
1490+ '#add-dymic-wrap' ,
1491+ ) as HTMLDivElement ;
1492+ if ( wrap . children . length > 0 ) {
1493+ return true ;
1494+ }
1495+ return Promise . reject ( ) ;
1496+ } ,
1497+ { timeout : 100 , interval : 10 } ,
1498+ ) ;
1499+ const wrap = container . querySelector ( '#add-dymic-wrap' ) as HTMLDivElement ;
1500+ expect ( wrap . children . length ) . toBeGreaterThan ( 0 ) ;
1501+ const children = wrap . children ;
1502+ Array . from ( children ) . forEach ( ( v , index ) => {
1503+ const input = container . querySelector (
1504+ `#dymic-${ index } -input` ,
1505+ ) as HTMLInputElement ;
1506+ expect ( Number ( input . value ) ) . toBe ( index ) ;
1507+ } ) ;
1508+ } ) ;
1509+
1510+ test ( 'remove' , async ( { expect } ) => {
1511+ const TestDemo = React . forwardRef ( ( props , ref ) => {
1512+ const { render, model, forceUpdate } = useForm < {
1513+ list : Array < { uid : string ; value : string } > ;
1514+ } > ( { list : [ ] } ) ;
1515+ const renderMapList = model . list . map ( ( v , index ) => {
1516+ const renderRemoveButton = (
1517+ < button
1518+ id = { `remove-item-${ index } -button` }
1519+ onClick = { ( ) => {
1520+ model . list . splice ( index , 1 ) ;
1521+ forceUpdate ( ) ;
1522+ } }
1523+ >
1524+ remove!
1525+ </ button >
1526+ ) ;
1527+ return (
1528+ < div id = { v . uid } key = { v . uid } >
1529+ { render ( `list.${ index } .value` ) (
1530+ < input id = { `dymic-remove-${ index } -input` } /> ,
1531+ ) }
1532+ { renderRemoveButton }
1533+ </ div >
1534+ ) ;
1535+ } ) ;
1536+ const renderButton = (
1537+ < button
1538+ id = "dymic-remove-add-button"
1539+ onClick = { ( ) => {
1540+ model . list . push ( {
1541+ uid : getUuid ( ) ,
1542+ value : `${ model . list . length } ` ,
1543+ } ) ;
1544+ forceUpdate ( ) ;
1545+ } }
1546+ >
1547+ add
1548+ </ button >
1549+ ) ;
1550+ useImperativeHandle ( ref , ( ) => ( {
1551+ getModalData ( ) {
1552+ return model ;
1553+ } ,
1554+ set ( arr : any [ ] ) {
1555+ model . list = arr ;
1556+ forceUpdate ( ) ;
1557+ } ,
1558+ } ) ) ;
1559+ return (
1560+ < >
1561+ < div id = "remove-dymic-wrap" > { renderMapList } </ div >
1562+ { renderButton }
1563+ </ >
1564+ ) ;
1565+ } ) ;
1566+
1567+ const demoRef = React . createRef ( ) as any ;
1568+
1569+ const { container } = testRender ( < TestDemo ref = { demoRef } /> ) ;
1570+ const addItem = ( count : number = 1 ) => {
1571+ const button = container . querySelector (
1572+ '#dymic-remove-add-button' ,
1573+ ) as HTMLButtonElement ;
1574+ Array . from ( { length : count } , ( x , y ) => y ) . forEach ( ( ) => {
1575+ button . click ( ) ;
1576+ } ) ;
1577+ } ;
1578+
1579+ addItem ( 2 ) ;
1580+
1581+ const getWrap = ( ) =>
1582+ container . querySelector ( '#remove-dymic-wrap' ) as HTMLDivElement ;
1583+
1584+ const getLen = ( ) => {
1585+ const wrap = getWrap ( ) ;
1586+ return wrap ?. children ?. length ;
1587+ } ;
1588+
1589+ const checkWrapChildrenLen = ( ) => {
1590+ const len = getLen ( ) ;
1591+ if ( len === 2 ) {
1592+ return true ;
1593+ }
1594+ return Promise . reject ( ) ;
1595+ } ;
1596+ await vi . waitFor ( ( ) => checkWrapChildrenLen ( ) , {
1597+ timeout : 100 ,
1598+ interval : 10 ,
1599+ } ) ;
1600+
1601+ const len = getLen ( ) ;
1602+ expect ( len ) . toBeGreaterThan ( 0 ) ;
1603+ const getInput = ( index : number ) => {
1604+ const input = container . querySelector (
1605+ `#dymic-remove-${ index } -input` ,
1606+ ) as HTMLInputElement ;
1607+ return input ;
1608+ } ;
1609+ const getInputValue = ( index : number ) => {
1610+ const input = getInput ( index ) ;
1611+ return input . value ;
1612+ } ;
1613+ const checkInputValue = ( ) => {
1614+ const wrap = getWrap ( ) ;
1615+ const children = wrap . children ;
1616+ Array . from ( children ) . forEach ( ( v , index ) => {
1617+ const value = getInputValue ( index ) ;
1618+ expect ( Number ( value ) ) . toBe ( index ) ;
1619+ } ) ;
1620+ } ;
1621+ checkInputValue ( ) ;
1622+ const removeAction = async ( ) => {
1623+ const removeButton = container . querySelector (
1624+ '#remove-item-0-button' ,
1625+ ) as HTMLButtonElement ;
1626+
1627+ removeButton . click ( ) ;
1628+ await vi . waitFor ( ( ) => {
1629+ const len = getLen ( ) ;
1630+ if ( len === 1 ) {
1631+ return true ;
1632+ }
1633+ return Promise . reject ( ) ;
1634+ } ) ;
1635+ // checkInputValue();
1636+
1637+ addItem ( ) ;
1638+
1639+ const changeInputValue = ( index : number ) => {
1640+ const input = getInput ( index ) ;
1641+ fireEvent . change ( input , { target : { value : 'testtest' } } ) ;
1642+ } ;
1643+
1644+ await vi . waitFor ( ( ) => {
1645+ const len = getLen ( ) ;
1646+ if ( len === 2 ) return true ;
1647+ return Promise . reject ( ) ;
1648+ } ) ;
1649+
1650+ changeInputValue ( 0 ) ;
1651+
1652+ expect ( getInputValue ( 0 ) ) . toBe ( 'testtest' ) ;
1653+
1654+ expect ( getInputValue ( 0 ) ) . not . toBe ( getInputValue ( 1 ) ) ;
1655+ const getModal = ( ) => {
1656+ const model = demoRef . current ?. getModalData ?.( ) ;
1657+ return model ;
1658+ } ;
1659+ const getModelListValue = ( index : number ) => {
1660+ const model = getModal ( ) ;
1661+ const list = model . list || [ ] ;
1662+ return list [ index ] . value ;
1663+ } ;
1664+
1665+ expect ( getModelListValue ( 0 ) ) . toBe ( getInputValue ( 0 ) ) ;
1666+ expect ( getModelListValue ( 0 ) ) . not . toBe ( getModelListValue ( 1 ) ) ;
1667+
1668+ return Promise . resolve ( ) ;
1669+ } ;
1670+
1671+ await removeAction ( ) ;
1672+ } ) ;
1673+
1674+ test ( 'assignment' , async ( ) => {
1675+ const TestDemo = React . forwardRef ( ( { } , ref ) => {
1676+ const { render, model, forceUpdate } = useForm < {
1677+ list : Array < { uid : string ; value : string } > ;
1678+ } > ( { list : [ ] } ) ;
1679+ const renderMapList = model . list . map ( ( v , index ) => {
1680+ return (
1681+ < div id = { v . uid } key = { v . uid } >
1682+ { render ( `list.${ index } .value` ) (
1683+ < input id = { `dymic-assignment-${ index } -input` } /> ,
1684+ ) }
1685+ </ div >
1686+ ) ;
1687+ } ) ;
1688+
1689+ useImperativeHandle ( ref , ( ) => ( {
1690+ getModalData ( ) {
1691+ return model ;
1692+ } ,
1693+ set ( arr : any [ ] ) {
1694+ model . list = arr ;
1695+ forceUpdate ( ) ;
1696+ } ,
1697+ } ) ) ;
1698+ return (
1699+ < >
1700+ < div id = "assign-dymic-wrap" > { renderMapList } </ div >
1701+ </ >
1702+ ) ;
1703+ } ) ;
1704+
1705+ const ref = React . createRef ( ) as any ;
1706+ const { container } = testRender ( < TestDemo ref = { ref } /> ) ;
1707+
1708+ const arr = [
1709+ { uid : getUuid ( ) , value : 'name' } ,
1710+ { uid : getUuid ( ) , value : 'age' } ,
1711+ ] ;
1712+ ref . current . set ( arr ) ;
1713+
1714+ const getWrap = ( ) =>
1715+ container . querySelector ( '#assign-dymic-wrap' ) as HTMLDivElement ;
1716+
1717+ const getLen = ( ) => {
1718+ const wrap = getWrap ( ) ;
1719+ return wrap ?. children ?. length ;
1720+ } ;
1721+
1722+ const checkWrapChildrenLen = ( ) => {
1723+ const len = getLen ( ) ;
1724+ if ( len === 2 ) {
1725+ return true ;
1726+ }
1727+ return Promise . reject ( ) ;
1728+ } ;
1729+
1730+ const getInput = ( index : number ) => {
1731+ const input = container . querySelector (
1732+ `#dymic-assignment-${ index } -input` ,
1733+ ) as HTMLInputElement ;
1734+ return input ;
1735+ } ;
1736+ const getInputValue = ( index : number ) => {
1737+ const input = getInput ( index ) ;
1738+ return input . value ;
1739+ } ;
1740+
1741+ const getModal = ( ) => {
1742+ const model = ref . current ?. getModalData ?.( ) ;
1743+ return model ;
1744+ } ;
1745+
1746+ const getModelListValue = ( index : number ) => {
1747+ const model = getModal ( ) ;
1748+ const list = model . list || [ ] ;
1749+ return list [ index ] . value ;
1750+ } ;
1751+
1752+ await vi . waitFor ( ( ) => checkWrapChildrenLen ( ) ) ;
1753+
1754+ Array . from ( getWrap ( ) . children ) . forEach ( ( v , index ) => {
1755+ const inputValue = getInputValue ( index ) ;
1756+ expect ( inputValue ) . toBe ( arr [ index ] . value ) ;
1757+ expect ( inputValue ) . toBe ( getModelListValue ( index ) ) ;
1758+ } ) ;
1759+
1760+ fireEvent . change ( getInput ( 0 ) , { target : { value : 'testtest' } } ) ;
1761+
1762+ fireEvent . change ( getInput ( 1 ) , { target : { value : 'testtesttwo' } } ) ;
1763+
1764+ expect ( getModelListValue ( 0 ) ) . toBe ( getInputValue ( 0 ) ) ;
1765+
1766+ expect ( getModelListValue ( 1 ) ) . toBe ( getInputValue ( 1 ) ) ;
1767+
1768+ expect ( getModelListValue ( 0 ) ) . not . toBe ( getInputValue ( 1 ) ) ;
1769+ } ) ;
1770+ } ) ;
0 commit comments