@@ -1433,6 +1433,311 @@ describe('ObjectPage', () => {
1433
1433
} ) ;
1434
1434
1435
1435
cypressPassThroughTestsFactory ( ObjectPage ) ;
1436
+
1437
+ it ( 'focus behavior & keyboard navigation' , ( ) => {
1438
+ cy . mount (
1439
+ < >
1440
+ < button data-testid = "start" > Start for tabbing chain</ button >
1441
+ < ObjectPage
1442
+ data-testid = "op"
1443
+ titleArea = { DPTitle }
1444
+ headerArea = { DPContent }
1445
+ footerArea = { Footer }
1446
+ style = { { height : '700px' } }
1447
+ >
1448
+ < ObjectPageSection titleText = "Goals" id = "goals" aria-label = "Goals" >
1449
+ < Form layout = "S1 M2 L3 XL3" labelSpan = "S12 M12 L12 XL12" >
1450
+ < FormItem labelContent = { < Label showColon > Evangelize the UI framework across the company</ Label > } >
1451
+ < Text > 4 days overdue - Cascaded</ Text >
1452
+ </ FormItem >
1453
+ < FormItem labelContent = { < Label showColon > Get trained in development management direction</ Label > } >
1454
+ < Text > Due Nov, 21</ Text >
1455
+ </ FormItem >
1456
+ < FormItem labelContent = { < Label showColon > Mentor junior developers</ Label > } >
1457
+ < Text > Due Dec, 31 - Cascaded</ Text >
1458
+ </ FormItem >
1459
+ </ Form >
1460
+ </ ObjectPageSection >
1461
+ < ObjectPageSection id = { 'dummy' } titleText = { 'Dummy' } aria-label = { 'Dummy' } >
1462
+ Dummy
1463
+ </ ObjectPageSection >
1464
+ < ObjectPageSection titleText = "Personal" id = "personal" aria-label = "Personal" >
1465
+ < ObjectPageSubSection
1466
+ titleText = "Connect"
1467
+ id = "personal-connect"
1468
+ aria-label = "Connect"
1469
+ actions = {
1470
+ < >
1471
+ < Button design = { ButtonDesign . Emphasized } data-testid = "customAction" >
1472
+ Custom Action
1473
+ </ Button >
1474
+ </ >
1475
+ }
1476
+ >
1477
+ < Form style = { { alignItems : 'baseline' } } >
1478
+ < FormGroup headerText = "Phone Numbers" >
1479
+ < FormItem labelContent = { < Label showColon > Home</ Label > } >
1480
+ < Text > +1 234-567-8901</ Text >
1481
+ < Text > +1 234-567-5555</ Text >
1482
+ </ FormItem >
1483
+ </ FormGroup >
1484
+ < FormGroup headerText = "Social Accounts" >
1485
+ < FormItem labelContent = { < Label showColon > LinkedIn</ Label > } >
1486
+ < Text > /DeniseSmith</ Text >
1487
+ </ FormItem >
1488
+ < FormItem labelContent = { < Label showColon > Twitter</ Label > } >
1489
+ < Text > @DeniseSmith</ Text >
1490
+ </ FormItem >
1491
+ </ FormGroup >
1492
+ < FormGroup headerText = "Addresses" >
1493
+ < FormItem labelContent = { < Label showColon > Home Address</ Label > } >
1494
+ < Text > 2096 Mission Street</ Text >
1495
+ </ FormItem >
1496
+ < FormItem labelContent = { < Label showColon > Mailing Address</ Label > } >
1497
+ < Text > PO Box 32114</ Text >
1498
+ </ FormItem >
1499
+ </ FormGroup >
1500
+ < FormGroup headerText = "Mailing Address" >
1501
+ < FormItem labelContent = { < Label showColon > Work</ Label > } >
1502
+
1503
+ </ FormItem >
1504
+ </ FormGroup >
1505
+ </ Form >
1506
+ </ ObjectPageSubSection >
1507
+ < ObjectPageSubSection
1508
+ titleText = "Payment Information"
1509
+ id = "personal-payment-information"
1510
+ aria-label = "Payment Information"
1511
+ >
1512
+ < Form >
1513
+ < FormGroup headerText = "Salary" >
1514
+ < FormItem labelContent = { < Label showColon > Bank Transfer</ Label > } >
1515
+ < Text > Money Bank, Inc.</ Text >
1516
+ </ FormItem >
1517
+ </ FormGroup >
1518
+ < FormGroup headerText = "Payment method for Expenses" >
1519
+ < FormItem labelContent = { < Label showColon > Extra Travel Expenses</ Label > } >
1520
+ < Text > Cash 100 USD</ Text >
1521
+ </ FormItem >
1522
+ </ FormGroup >
1523
+ </ Form >
1524
+ </ ObjectPageSubSection >
1525
+ </ ObjectPageSection >
1526
+ < ObjectPageSection titleText = "Employment" id = "employment" aria-label = "Employment" >
1527
+ < ObjectPageSubSection
1528
+ titleText = "Job Information"
1529
+ id = "employment-job-information"
1530
+ aria-label = "Job Information"
1531
+ >
1532
+ < Form >
1533
+ < FormItem labelContent = { < Label showColon > Job Classification</ Label > } >
1534
+ < FlexBox direction = { FlexBoxDirection . Column } >
1535
+ < Text > Senior UI Developer</ Text >
1536
+ < Label > (UIDEV-SR)</ Label >
1537
+ </ FlexBox >
1538
+ </ FormItem >
1539
+ < FormItem labelContent = { < Label showColon > Job Title</ Label > } >
1540
+ < Text > Developer</ Text >
1541
+ </ FormItem >
1542
+ < FormItem labelContent = { < Label showColon > Employee Class</ Label > } >
1543
+ < Text > Employee</ Text >
1544
+ </ FormItem >
1545
+ < FormItem labelContent = { < Label showColon > Manager</ Label > } >
1546
+ < FlexBox direction = { FlexBoxDirection . Column } >
1547
+ < Text > Dan Smith</ Text >
1548
+ < Label > Development Manager</ Label >
1549
+ </ FlexBox >
1550
+ </ FormItem >
1551
+ < FormItem labelContent = { < Label showColon > Pay Grade</ Label > } >
1552
+ < Text > Salary Grade 18 (GR-14)</ Text >
1553
+ </ FormItem >
1554
+ < FormItem labelContent = { < Label showColon > FTE</ Label > } >
1555
+ < Text > 1</ Text >
1556
+ </ FormItem >
1557
+ </ Form >
1558
+ </ ObjectPageSubSection >
1559
+ < ObjectPageSubSection
1560
+ titleText = "Employee Details"
1561
+ id = "employment-employee-details"
1562
+ aria-label = "Employee Details"
1563
+ >
1564
+ < Form >
1565
+ < FormItem labelContent = { < Label showColon > Start Date</ Label > } >
1566
+ < Text > Jan 01, 2018</ Text >
1567
+ </ FormItem >
1568
+ < FormItem labelContent = { < Label showColon > End Date</ Label > } >
1569
+ < Text > Dec 31, 9999</ Text >
1570
+ </ FormItem >
1571
+ < FormItem labelContent = { < Label showColon > Payroll Start Date</ Label > } >
1572
+ < Text > Jan 01, 2018</ Text >
1573
+ </ FormItem >
1574
+ < FormItem labelContent = { < Label showColon > Benefits Start Date</ Label > } >
1575
+ < Text > Jul 01, 2018</ Text >
1576
+ </ FormItem >
1577
+ < FormItem labelContent = { < Label showColon > Company Car Eligibility</ Label > } >
1578
+ < Text > Jan 01, 2021</ Text >
1579
+ </ FormItem >
1580
+ < FormItem labelContent = { < Label showColon > Equity Start Date</ Label > } >
1581
+ < Text > Jul 01, 2018</ Text >
1582
+ </ FormItem >
1583
+ </ Form >
1584
+ </ ObjectPageSubSection >
1585
+ < ObjectPageSubSection
1586
+ titleText = "Job Relationship"
1587
+ id = "employment-job-relationship"
1588
+ aria-label = "Job Relationship"
1589
+ >
1590
+ < Form >
1591
+ < FormItem labelContent = { < Label showColon > Manager</ Label > } >
1592
+ < Text > John Doe</ Text >
1593
+ </ FormItem >
1594
+ < FormItem labelContent = { < Label showColon > Scrum Master</ Label > } >
1595
+ < Text > Michael Adams</ Text >
1596
+ </ FormItem >
1597
+ < FormItem labelContent = { < Label showColon > Product Owner</ Label > } >
1598
+ < Text > John Miller</ Text >
1599
+ </ FormItem >
1600
+ </ Form >
1601
+ </ ObjectPageSubSection >
1602
+ </ ObjectPageSection >
1603
+ < ObjectPageSection id = { '5' } titleText = { 'SingleSectionInput' } aria-label = "SingleSectionInput" >
1604
+ < Input data-testid = "single" />
1605
+ </ ObjectPageSection >
1606
+ < ObjectPageSection id = { '6' } titleText = { 'SubSectionsInput' } aria-label = "SubSectionsInput" >
1607
+ < ObjectPageSubSection id = "6.1" titleText = "6.1" aria-label = "6.1" >
1608
+ Some Text
1609
+ </ ObjectPageSubSection >
1610
+ < ObjectPageSubSection id = "6.2" titleText = "6.2" aria-label = "6.2" >
1611
+ < Input data-testid = "sub" />
1612
+ </ ObjectPageSubSection >
1613
+ </ ObjectPageSection >
1614
+ </ ObjectPage >
1615
+ </ > ,
1616
+ ) ;
1617
+
1618
+ cy . get ( '[data-component-name="ObjectPageSection"]' ) . as ( 'sections' ) ;
1619
+ cy . get ( '@sections' ) . eq ( 0 ) . should ( 'have.attr' , 'tabindex' , 0 ) ;
1620
+ cy . get ( '@sections' ) . each ( ( section , index ) => {
1621
+ if ( index !== 0 ) {
1622
+ cy . wrap ( section ) . should ( 'have.attr' , 'tabindex' , - 1 ) ;
1623
+ }
1624
+ } ) ;
1625
+ cy . get ( '[data-component-name="ObjectPageSubSection"]' ) . should ( 'have.attr' , 'tabindex' , - 1 ) ;
1626
+
1627
+ cy . findByTestId ( 'start' ) . focus ( ) ;
1628
+ // breadcrumbs
1629
+ cy . realPress ( 'Tab' ) ;
1630
+ //toolbar
1631
+ cy . realPress ( 'Tab' ) ;
1632
+ cy . realPress ( 'Tab' ) ;
1633
+ // header content (links)
1634
+ cy . realPress ( 'Tab' ) ;
1635
+ cy . realPress ( 'Tab' ) ;
1636
+ cy . realPress ( 'Tab' ) ;
1637
+ // anchor buttons
1638
+ cy . realPress ( 'Tab' ) ;
1639
+ cy . realPress ( 'Tab' ) ;
1640
+ // tabbar
1641
+ cy . realPress ( 'Tab' ) ;
1642
+ // first section
1643
+ cy . realPress ( 'Tab' ) ;
1644
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Goals' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1645
+ // Personal: custom action
1646
+ cy . realPress ( 'Tab' ) ;
1647
+ cy . findByTestId ( 'customAction' ) . should ( 'be.focused' ) ;
1648
+ // SingleSectionInput
1649
+ cy . realPress ( 'Tab' ) ;
1650
+ cy . findByTestId ( 'single' ) . should ( 'be.focused' ) ;
1651
+ // 6.2 input
1652
+ cy . realPress ( 'Tab' ) ;
1653
+ cy . findByTestId ( 'sub' ) . should ( 'be.focused' ) ;
1654
+ //footer
1655
+ cy . realPress ( 'Tab' ) ;
1656
+ cy . findByTestId ( 'footer-accept-btn' ) . should ( 'be.focused' ) ;
1657
+ // 6.2 input
1658
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1659
+ cy . findByTestId ( 'sub' ) . should ( 'be.focused' ) ;
1660
+ // 6.2 subsection
1661
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1662
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , '6.2' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1663
+ // SubSectionsInput
1664
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1665
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'SubSectionsInput' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1666
+ // SingleSectionInput
1667
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1668
+ cy . findByTestId ( 'single' ) . should ( 'be.focused' ) ;
1669
+ // section SingleSectionInput
1670
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1671
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'SingleSectionInput' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1672
+ // Personal: custom action btn
1673
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1674
+ cy . findByTestId ( 'customAction' ) . should ( 'be.focused' ) ;
1675
+ // Personal: Connect - subsection
1676
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1677
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Connect' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1678
+ // Personal: section
1679
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1680
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Personal' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1681
+ // tabbar
1682
+ cy . realPress ( [ 'Shift' , 'Tab' ] ) ;
1683
+
1684
+ cy . get ( '@sections' ) . eq ( 2 ) . should ( 'have.attr' , 'tabindex' , 0 ) ;
1685
+ cy . get ( '@sections' ) . each ( ( section , index ) => {
1686
+ if ( index !== 2 ) {
1687
+ cy . wrap ( section ) . should ( 'have.attr' , 'tabindex' , - 1 ) ;
1688
+ }
1689
+ } ) ;
1690
+ cy . get ( '[data-component-name="ObjectPageSubSection"]' ) . should ( 'have.attr' , 'tabindex' , - 1 ) ;
1691
+
1692
+ // click first Tab
1693
+ cy . focused ( ) . realClick ( ) ;
1694
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Goals' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1695
+
1696
+ // arrow section navigation
1697
+ cy . realPress ( 'ArrowUp' ) ;
1698
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Goals' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1699
+ cy . realPress ( 'ArrowDown' ) ;
1700
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Dummy' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1701
+ cy . realPress ( 'ArrowDown' ) ;
1702
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Personal' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1703
+ cy . realPress ( 'ArrowDown' ) ;
1704
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Employment' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1705
+ cy . realPress ( 'ArrowDown' ) ;
1706
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'SingleSectionInput' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1707
+ cy . realPress ( 'ArrowDown' ) ;
1708
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'SubSectionsInput' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1709
+ cy . realPress ( 'ArrowDown' ) ;
1710
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'SubSectionsInput' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1711
+
1712
+ // arrow subsection navigation
1713
+ cy . realPress ( 'Tab' ) ;
1714
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , '6.1' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1715
+ cy . realPress ( 'ArrowUp' ) ;
1716
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , '6.1' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1717
+ cy . realPress ( 'ArrowDown' ) ;
1718
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , '6.2' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1719
+
1720
+ cy . get ( '[ui5-tabcontainer]' ) . findUi5TabOpenPopoverButtonByText ( 'Employment' ) . click ( ) ;
1721
+ cy . get ( '[ui5-responsive-popover]' ) . should ( 'be.visible' ) ;
1722
+ cy . realPress ( 'ArrowDown' ) ;
1723
+ cy . realPress ( 'Enter' ) ;
1724
+ cy . focused ( ) . should ( 'have.attr' , 'aria-label' , 'Employee Details' ) . and ( 'have.attr' , 'tabindex' , 0 ) ;
1725
+
1726
+ cy . get ( '[data-component-name="ObjectPageSection"]' ) . as ( 'sections' ) ;
1727
+ cy . get ( '@sections' ) . eq ( 3 ) . should ( 'have.attr' , 'tabindex' , 0 ) ;
1728
+ cy . get ( '@sections' ) . each ( ( section , index ) => {
1729
+ if ( index !== 3 ) {
1730
+ cy . wrap ( section ) . should ( 'have.attr' , 'tabindex' , - 1 ) ;
1731
+ }
1732
+ } ) ;
1733
+ cy . get ( '[data-component-name="ObjectPageSubSection"]' ) . as ( 'subsections' ) ;
1734
+ cy . get ( '@subsections' ) . eq ( 3 ) . should ( 'have.attr' , 'tabindex' , 0 ) ;
1735
+ cy . get ( '@subsections' ) . each ( ( section , index ) => {
1736
+ if ( index !== 3 ) {
1737
+ cy . wrap ( section ) . should ( 'have.attr' , 'tabindex' , - 1 ) ;
1738
+ }
1739
+ } ) ;
1740
+ } ) ;
1436
1741
} ) ;
1437
1742
1438
1743
const DPTitle = (
@@ -1602,7 +1907,9 @@ const Footer = (
1602
1907
design = { BarDesign . FloatingFooter }
1603
1908
endContent = {
1604
1909
< >
1605
- < Button design = { ButtonDesign . Positive } > Accept</ Button >
1910
+ < Button design = { ButtonDesign . Positive } data-testid = "footer-accept-btn" >
1911
+ Accept
1912
+ </ Button >
1606
1913
< Button design = { ButtonDesign . Negative } > Reject</ Button >
1607
1914
</ >
1608
1915
}
0 commit comments