Mirror: React hooks for accessible, common web interactions. UI super powers without the UI.
at v0.1.5 3.0 kB view raw
1import React, { useState, useRef } from 'react'; 2import { mount } from '@cypress/react'; 3 4import { useDismissable } from '../useDismissable'; 5 6const Dialog = ({ focusLoss }: { focusLoss?: boolean }) => { 7 const [visible, setVisible] = useState(true); 8 const ref = useRef<HTMLDivElement>(null); 9 10 const onDismiss = () => setVisible(false); 11 useDismissable(ref, onDismiss, { focusLoss, disabled: !visible }); 12 13 return ( 14 <div ref={ref} role="dialog" style={{ display: visible ? 'block' : 'none' }}> 15 <button className="inside">focusable</button> 16 </div> 17 ); 18}; 19 20it('is dismissed by clicking outside', () => { 21 mount( 22 <main> 23 <button className="outside">outside</button> 24 <Dialog /> 25 </main> 26 ); 27 28 cy.get('.inside').as('inside').realClick(); 29 cy.get('@inside').should('be.visible'); 30 cy.get('.outside').first().realClick(); 31 cy.get('@inside').should('not.be.visible'); 32}); 33 34it('is not dismissed by clicking outside when it does not have priority', () => { 35 mount( 36 <main> 37 <button className="outside">outside</button> 38 <Dialog /> 39 <Dialog /> 40 </main> 41 ); 42 43 cy.get('.inside').as('inside').should('be.visible'); 44 // at first not dismissed 45 cy.get('.outside').first().realClick(); 46 cy.get('@inside').should('be.visible'); 47 // dismissed when the second Dialog loses focus 48 cy.get('.outside').first().realClick(); 49 cy.get('@inside').should('not.be.visible'); 50}); 51 52it('is dismissed by tapping outside', () => { 53 mount( 54 <main> 55 <button className="outside">outside</button> 56 <Dialog /> 57 </main> 58 ); 59 60 cy.get('.inside').as('inside').realClick(); 61 cy.get('@inside').should('be.visible'); 62 cy.get('.outside').first().realTouch(); 63 cy.get('@inside').should('not.be.visible'); 64}); 65 66it('is dismissed by pressing Escape', () => { 67 mount( 68 <main> 69 <button className="outside">outside</button> 70 <Dialog /> 71 </main> 72 ); 73 74 cy.get('.inside').as('inside').should('be.visible'); 75 cy.realPress('Escape'); 76 cy.get('@inside').should('not.be.visible'); 77}); 78 79it('is not dismissed by pressing Escape when it does not have priority', () => { 80 mount( 81 <main> 82 <button className="outside">outside</button> 83 <Dialog /> 84 <Dialog /> 85 </main> 86 ); 87 88 cy.get('.inside').as('inside').should('be.visible'); 89 // at first not dismissed 90 cy.realPress('Escape'); 91 cy.get('@inside').should('be.visible'); 92 // dismissed when the second Dialog loses focus 93 cy.realPress('Escape'); 94 cy.get('@inside').should('not.be.visible'); 95}); 96 97it('is dismissed when focus moves out of it, with focus loss active', () => { 98 mount( 99 <main> 100 <button className="outside">outside</button> 101 <Dialog focusLoss /> 102 </main> 103 ); 104 105 cy.get('.inside').as('inside').should('be.visible'); 106 cy.get('@inside').focus(); 107 cy.get('@inside').should('be.visible'); 108 // is dismissed when it loses focus 109 cy.realPress(['Shift', 'Tab']); 110 cy.focused().contains('outside'); 111 cy.get('@inside').should('not.be.visible'); 112});