@@ -1433,6 +1433,311 @@ describe('ObjectPage', () => {
14331433 } ) ;
14341434
14351435 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+ } ) ;
14361741} ) ;
14371742
14381743const DPTitle = (
@@ -1602,7 +1907,9 @@ const Footer = (
16021907 design = { BarDesign . FloatingFooter }
16031908 endContent = {
16041909 < >
1605- < Button design = { ButtonDesign . Positive } > Accept</ Button >
1910+ < Button design = { ButtonDesign . Positive } data-testid = "footer-accept-btn" >
1911+ Accept
1912+ </ Button >
16061913 < Button design = { ButtonDesign . Negative } > Reject</ Button >
16071914 </ >
16081915 }
0 commit comments