Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 48 additions & 44 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ declare global {
namespace Cypress {
interface Chainable {
tab(options?: Partial<{ shift: boolean }>): Chainable;

/**
* Presses the tab key until a predicate element is true.
* It accepts a callback for finding the target element, and an optional shift element to tab backwards.
* This commmand is specially useful to avoid chaining `.realPress("Tab")` multiple times before reaching an element.
*
* @requires `cypress-real-events` needs to be installed
*
* @example
*
* // Press tab until cypress finds the tab with the name "Transaction History"
* cy.tabUntil(() => cy.getTab("Transaction History"));
*
* // Press tab until cypress finds the tab with the name "Transaction History",
* // BUT travel backwards, using the `Shift+Tab` key combo
* cy.tabUntil(() => cy.getTab("Transaction History", true));
*/
tabUntil<GenericCallback extends Cypress.Chainable<JQuery<HTMLElement>>>(
element: () => GenericCallback,
shift?: boolean,
Expand All @@ -36,48 +53,35 @@ declare global {
}
}

/**
* Presses the tab key until a predicate element is true.
* It accepts a callback for finding the target element, and an optional shift element to tab backwards.
* This commmand is specially useful to avoid chaining `.realPress("Tab")` multiple times before reaching an element.
*
* @requires `cypress-real-events` needs to be installed
*
* @example
*
* // Press tab until cypress finds the tab with the name "Transaction History"
* cy.tabUntil(() => cy.getTab("Transaction History"));
*
* // Press tab until cypress finds the tab with the name "Transaction History",
* // BUT travel backwards, using the `Shift+Tab` key combo
* cy.tabUntil(() => cy.getTab("Transaction History", true));
*/
Cypress.Commands.add(
"tabUntil",
/**
* @param getElement
* @param shift
* @returns
*/
<GenericCallback extends Cypress.Chainable<JQuery<HTMLElement>>>(
getElement: () => GenericCallback,
shift = false,
) => {
return recurse(
() => getElement(),
/**
* Element assertion.
*
* @param {JQuery<HTMLElement>} $el
* @returns {boolean}
*/
($el: JQuery<HTMLElement>): boolean => $el.is(":focus"),
{
log: "Found the element!",
post() {
cy.focused().realPress(shift ? ["Shift", "Tab"] : "Tab");
},
function tab<GenericSubject>(
prevSubject: GenericSubject,
options: Partial<{ shift: boolean }> = { shift: false },
) {
return cy.wrap(prevSubject).realPress(options.shift ? ["Shift", "Tab"] : "Tab");
}

function tabUntil<GenericCallback extends Cypress.Chainable<JQuery<HTMLElement>>>(
getElement: () => GenericCallback,
shift = false,
) {
return recurse(
() => getElement(),
/**
* Element assertion.
*
* @param {JQuery<HTMLElement>} $el
* @returns {boolean}
*/
($el: JQuery<HTMLElement>): boolean => $el.is(":focus"),
{
log: "Found the element!",
post() {
cy.focused().realPress(shift ? ["Shift", "Tab"] : "Tab");
},
).should("have.focus");
},
);
},
).should("have.focus");
}

Cypress.Commands.add("tab", { prevSubject: ["element"] }, tab);

Cypress.Commands.add("tabUntil", tabUntil);
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* The copyright of this file belongs to Feedzai. The file cannot be
* reproduced in whole or in part, stored in a retrieval system, transmitted
* in any form, or by any means electronic, mechanical, or otherwise, without
* the prior permission of the owner. Please refer to the terms of the license
* agreement.
*
* (c) 2024 Feedzai, Rights Reserved.
*/
.table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}

tr:nth-child(even) {
background-color: #dddddd;
}

tr:focus-within {
outline: 2px solid blue;
background-color: lightblue;
}
}

.dialog {
position: absolute;
inset: 0;
margin: auto;
max-width: 50vw;
display: grid;
place-items: center;
background-color: white;
outline: 2px solid black;
height: 50vh;

&:focus-within {
outline-color: blue;
}
}
100 changes: 100 additions & 0 deletions cypress/test/components/focus-manager/demos/MultipleManagers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Please refer to the terms of the license
* agreement.
*
* (c) 2024 Feedzai, Rights Reserved.
*/
import React from "react";
import { useState } from "react";
import { FocusManager } from "src/components";
import styles from "./MultipleManagers.module.scss";

export function MultipleManagers() {
const [isOpen, setIsOpen] = useState(false);
const [isSecondOpen, setIsSecondOpen] = useState(false);
return (
<div>
<button type="button">I don't do anything</button>
<table className={styles.table}>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td>
<button type="button" onClick={() => setIsOpen(true)}>
Open Dialog
</button>
</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td>
{" "}
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td>
{" "}
<button type="button">I don't do anything</button>
</td>
</tr>
</table>
{isOpen ? (
<div role="dialog" className={styles.dialog}>
<FocusManager>
<button type="button" onClick={() => setIsOpen(false)}>
Close Dialog
</button>
<input data-testid="fdz-js-input-1" />
<input data-testid="fdz-js-input-2" />
<input data-testid="fdz-js-input-3" />
<button type="button" onClick={() => setIsSecondOpen(!isSecondOpen)}>
Open Second Dialog
</button>
</FocusManager>
</div>
) : null}
{isSecondOpen ? (
<div role="dialog" className={styles.dialog}>
<FocusManager>
<button type="button" onClick={() => setIsSecondOpen(false)}>
Close Second Dialog
</button>
<input data-testid="fdz-js-input-4" />
<input data-testid="fdz-js-input-5" />
<input data-testid="fdz-js-input-6" />
</FocusManager>
</div>
) : null}
</div>
);
}
78 changes: 78 additions & 0 deletions cypress/test/components/focus-manager/demos/RestoreFocus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Please refer to the terms of the license
* agreement.
*
* (c) 2024 Feedzai, Rights Reserved.
*/
import React from "react";
import { useState } from "react";
import { FocusManager } from "src/components";
import styles from "./MultipleManagers.module.scss";

export function RestoreFocus() {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<table className={styles.table}>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td>
<button type="button" onClick={() => setIsOpen(true)}>
Open Dialog
</button>
</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td>
<button type="button">I don't do anything</button>
</td>
</tr>
</table>
{isOpen ? (
<div role="dialog" className={styles.dialog}>
<FocusManager>
<button type="button" onClick={() => setIsOpen(false)}>
Close Dialog
</button>
</FocusManager>
</div>
) : null}
</div>
);
}
8 changes: 8 additions & 0 deletions cypress/test/components/focus-manager/demos/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Please refer to the terms of the license
* agreement.
*
* (c) 2024 Feedzai, Rights Reserved.
*/
export * from "./MultipleManagers";
export * from "./RestoreFocus";
Loading
Loading