fix: add testing library eslint rules (#31028)

Added recommended rules for testing library

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added `data-testid` attributes across various components for improved
test identification.

- **Tests**
- Enhanced test cases with asynchronous handling (`async`/`await`) for
more reliable user interaction simulations.
- Transitioned to using `getByTestId` instead of `queryByTestId` for
better assertion reliability in tests.
- Added `await` before the `userEvent.click(el)` statement in the
ChartWidget test file.
- Updated the destructured variable names from `queryByTestId` to
`getByTestId` in the DividerWidget test file for improved clarity.
- Added an import for `screen` from "@testing-library/react" and updated
element querying in the TabsWidget test file.

- **Chores**
- Updated ESLint configurations to include testing-library plugins and
rules, improving code quality and consistency in test files.
- Removed unnecessary `cleanup` function calls after tests, following
best practices for test cleanup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Valera Melnikov 2024-02-12 18:59:10 +03:00 committed by GitHub
parent fa0eda6229
commit d7cd02a45d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 273 additions and 229 deletions

View File

@ -16,12 +16,14 @@
"react-hooks", "react-hooks",
"sort-destructure-keys", "sort-destructure-keys",
"cypress", "cypress",
"testing-library",
"jest" "jest"
], ],
"extends": [ "extends": [
"plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
"plugin:cypress/recommended", "plugin:cypress/recommended",
"plugin:testing-library/react",
// Note: Please keep this as the last config to make sure that this (and by extension our .prettierrc file) overrides all configuration above it // Note: Please keep this as the last config to make sure that this (and by extension our .prettierrc file) overrides all configuration above it
// https://www.npmjs.com/package/eslint-plugin-prettier#recommended-configuration // https://www.npmjs.com/package/eslint-plugin-prettier#recommended-configuration
"plugin:prettier/recommended" "plugin:prettier/recommended"
@ -35,6 +37,13 @@
"project": "./tsconfig.json" "project": "./tsconfig.json"
}, },
"rules": { "rules": {
"testing-library/consistent-data-testid": [
"warn",
{
"testIdPattern": "^t--[a-zA-Z0-9_.-]*$",
"testIdAttribute": ["data-testid"]
}
],
"@typescript-eslint/consistent-type-definitions": "error", "@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/prefer-nullish-coalescing": "error", "@typescript-eslint/prefer-nullish-coalescing": "error",
"@typescript-eslint/promise-function-async": "error", "@typescript-eslint/promise-function-async": "error",

View File

@ -13,6 +13,12 @@ const baseNoRestrictedImports =
const eslintConfig = { const eslintConfig = {
extends: ["./.eslintrc.base.json"], extends: ["./.eslintrc.base.json"],
rules: { rules: {
"testing-library/no-container": "off",
"testing-library/no-node-access": "off",
"testing-library/no-debugging-utils": "off",
"testing-library/prefer-screen-queries": "off",
"testing-library/render-result-naming-convention": "off",
"testing-library/no-unnecessary-act": "off",
"@typescript-eslint/prefer-nullish-coalescing": "off", "@typescript-eslint/prefer-nullish-coalescing": "off",
"@typescript-eslint/strict-boolean-expressions": "off", "@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",

View File

@ -329,6 +329,7 @@
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-sort-destructure-keys": "^1.5.0", "eslint-plugin-sort-destructure-keys": "^1.5.0",
"eslint-plugin-storybook": "^0.6.15", "eslint-plugin-storybook": "^0.6.15",
"eslint-plugin-testing-library": "^6.2.0",
"esm": "^3.2.25", "esm": "^3.2.25",
"factory.ts": "^0.5.1", "factory.ts": "^0.5.1",
"husky": "^8.0.0", "husky": "^8.0.0",

View File

@ -858,6 +858,7 @@ export function RenderDropdownOptions(props: DropdownOptionsProps) {
<DropdownWrapper <DropdownWrapper
className="ads-dropdown-options-wrapper" className="ads-dropdown-options-wrapper"
data-cy="dropdown-options-wrapper" data-cy="dropdown-options-wrapper"
// eslint-disable-next-line testing-library/consistent-data-testid
data-testid="dropdown-options-wrapper" data-testid="dropdown-options-wrapper"
isOpen={props.isOpen} isOpen={props.isOpen}
width={optionWidth} width={optionWidth}

View File

@ -33,18 +33,16 @@ describe("@design-system/widgets/Button", () => {
render(<Button isLoading />); render(<Button isLoading />);
expect(screen.getByRole("button")).toHaveAttribute("data-loading"); expect(screen.getByRole("button")).toHaveAttribute("data-loading");
// eslint-disable-next-line testing-library/no-node-access
const icon = screen.getByRole("button").querySelector("[data-icon]"); const icon = screen.getByRole("button").querySelector("[data-icon]");
expect(icon).toBeInTheDocument(); expect(icon).toBeInTheDocument();
}); });
it("renders icon when passed", () => { it("renders icon when passed", () => {
const { container } = render(<Button icon="star" />); render(<Button icon="star" />);
// Note: using testid=t--fallack-icon as the icon is rendered lazily and the fallback component // Note: using testid=t--fallack-icon as the icon is rendered lazily and the fallback component
// has a testid // has a testid
const icon = container.querySelector( const icon = screen.getByTestId("t--fallback-icon");
"button [data-testid='t--fallback-icon']",
) as HTMLElement;
expect(icon).toBeInTheDocument(); expect(icon).toBeInTheDocument();
}); });

View File

@ -27,7 +27,7 @@ describe("@design-system/widgets/Checkbox", () => {
expect(screen.getByText("Click me")).toBeInTheDocument(); expect(screen.getByText("Click me")).toBeInTheDocument();
}); });
it("should render uncontrolled checkbox", () => { it("should render uncontrolled checkbox", async () => {
render( render(
<Checkbox defaultSelected onChange={onChangeSpy}> <Checkbox defaultSelected onChange={onChangeSpy}>
Checkbox Checkbox
@ -36,7 +36,7 @@ describe("@design-system/widgets/Checkbox", () => {
const checkbox = screen.getByRole("checkbox"); const checkbox = screen.getByRole("checkbox");
expect(checkbox).toBeChecked(); expect(checkbox).toBeChecked();
userEvent.click(checkbox); await userEvent.click(checkbox);
expect(onChangeSpy).toHaveBeenCalled(); expect(onChangeSpy).toHaveBeenCalled();
expect(screen.getByRole("checkbox")).not.toBeChecked(); expect(screen.getByRole("checkbox")).not.toBeChecked();
}); });
@ -64,6 +64,7 @@ describe("@design-system/widgets/Checkbox", () => {
it("should render indeterminate checkbox", () => { it("should render indeterminate checkbox", () => {
const { container } = render(<Checkbox isIndeterminate>Checkbox</Checkbox>); const { container } = render(<Checkbox isIndeterminate>Checkbox</Checkbox>);
// eslint-disable-next-line testing-library/no-container,testing-library/no-node-access
const label = container.querySelector("label") as HTMLElement; const label = container.querySelector("label") as HTMLElement;
const checkbox = screen.getByRole("checkbox") as HTMLInputElement; const checkbox = screen.getByRole("checkbox") as HTMLInputElement;
@ -74,6 +75,7 @@ describe("@design-system/widgets/Checkbox", () => {
it("should be able to render custom icon", () => { it("should be able to render custom icon", () => {
const { container } = render(<Checkbox icon={EmotionHappyLineIcon} />); const { container } = render(<Checkbox icon={EmotionHappyLineIcon} />);
// eslint-disable-next-line testing-library/no-container,testing-library/no-node-access
const icon = container.querySelector("label [data-icon]") as HTMLElement; const icon = container.querySelector("label [data-icon]") as HTMLElement;
expect(icon).toBeInTheDocument(); expect(icon).toBeInTheDocument();
}); });

View File

@ -7,7 +7,7 @@ import { CheckboxGroup } from "../";
import { Checkbox } from "../../Checkbox"; import { Checkbox } from "../../Checkbox";
describe("@design-system/widgets/CheckboxGroup", () => { describe("@design-system/widgets/CheckboxGroup", () => {
it("should render the checkbox group", () => { it("should render the checkbox group", async () => {
const { container } = render( const { container } = render(
<CheckboxGroup label="Checkbox Group"> <CheckboxGroup label="Checkbox Group">
<Checkbox value="value-1">Value 1</Checkbox> <Checkbox value="value-1">Value 1</Checkbox>
@ -18,6 +18,7 @@ describe("@design-system/widgets/CheckboxGroup", () => {
expect(screen.getByText("Value 1")).toBeInTheDocument(); expect(screen.getByText("Value 1")).toBeInTheDocument();
expect(screen.getByText("Value 2")).toBeInTheDocument(); expect(screen.getByText("Value 2")).toBeInTheDocument();
// eslint-disable-next-line testing-library/no-container,testing-library/no-node-access
const label = container.querySelector("label") as HTMLElement; const label = container.querySelector("label") as HTMLElement;
expect(label).toHaveTextContent("Checkbox Group"); expect(label).toHaveTextContent("Checkbox Group");
@ -32,22 +33,25 @@ describe("@design-system/widgets/CheckboxGroup", () => {
expect(checkboxes[0]).not.toBeChecked(); expect(checkboxes[0]).not.toBeChecked();
expect(checkboxes[1]).not.toBeChecked(); expect(checkboxes[1]).not.toBeChecked();
userEvent.click(checkboxes[0]); await userEvent.click(checkboxes[0]);
expect(checkboxes[0]).toBeChecked(); expect(checkboxes[0]).toBeChecked();
userEvent.click(checkboxes[1]); await userEvent.click(checkboxes[1]);
expect(checkboxes[1]).toBeChecked(); expect(checkboxes[1]).toBeChecked();
}); });
it("should support custom props", () => { it("should support custom props", () => {
render( render(
<CheckboxGroup data-testid="checkbox-group" label="Checkbox Group Label"> <CheckboxGroup
data-testid="t--checkbox-group"
label="Checkbox Group Label"
>
<Checkbox value="value-1">Value 1</Checkbox> <Checkbox value="value-1">Value 1</Checkbox>
<Checkbox value="value-2">Value 2</Checkbox> <Checkbox value="value-2">Value 2</Checkbox>
</CheckboxGroup>, </CheckboxGroup>,
); );
const checkboxGroup = screen.getByTestId("checkbox-group"); const checkboxGroup = screen.getByTestId("t--checkbox-group");
expect(checkboxGroup).toBeInTheDocument(); expect(checkboxGroup).toBeInTheDocument();
}); });
@ -67,7 +71,7 @@ describe("@design-system/widgets/CheckboxGroup", () => {
expect(checkboxes[1]).toBeChecked(); expect(checkboxes[1]).toBeChecked();
}); });
it("should be able to fire onChange event", () => { it("should be able to fire onChange event", async () => {
const onChangeSpy = jest.fn(); const onChangeSpy = jest.fn();
render( render(
@ -78,7 +82,7 @@ describe("@design-system/widgets/CheckboxGroup", () => {
); );
const checkboxes = screen.getAllByRole("checkbox"); const checkboxes = screen.getAllByRole("checkbox");
userEvent.click(checkboxes[0]); await userEvent.click(checkboxes[0]);
expect(onChangeSpy).toHaveBeenCalled(); expect(onChangeSpy).toHaveBeenCalled();
}); });

View File

@ -7,7 +7,7 @@ import { RadioGroup } from "../";
import { Radio } from "../../Radio"; import { Radio } from "../../Radio";
describe("@design-system/widgets/RadioGroup", () => { describe("@design-system/widgets/RadioGroup", () => {
it("should render the Radio group", () => { it("should render the Radio group", async () => {
const { container } = render( const { container } = render(
<RadioGroup label="Radio Group"> <RadioGroup label="Radio Group">
<Radio value="value-1">Value 1</Radio> <Radio value="value-1">Value 1</Radio>
@ -18,6 +18,7 @@ describe("@design-system/widgets/RadioGroup", () => {
expect(screen.getByText("Value 1")).toBeInTheDocument(); expect(screen.getByText("Value 1")).toBeInTheDocument();
expect(screen.getByText("Value 2")).toBeInTheDocument(); expect(screen.getByText("Value 2")).toBeInTheDocument();
// eslint-disable-next-line testing-library/no-container,testing-library/no-node-access
const label = container.querySelector("label") as HTMLElement; const label = container.querySelector("label") as HTMLElement;
expect(label).toHaveTextContent("Radio Group"); expect(label).toHaveTextContent("Radio Group");
@ -32,24 +33,24 @@ describe("@design-system/widgets/RadioGroup", () => {
expect(options[0]).not.toBeChecked(); expect(options[0]).not.toBeChecked();
expect(options[1]).not.toBeChecked(); expect(options[1]).not.toBeChecked();
userEvent.click(options[0]); await userEvent.click(options[0]);
expect(options[0]).toBeChecked(); expect(options[0]).toBeChecked();
userEvent.click(options[1]); await userEvent.click(options[1]);
expect(options[0]).not.toBeChecked(); expect(options[0]).not.toBeChecked();
expect(options[1]).toBeChecked(); expect(options[1]).toBeChecked();
}); });
it("should support custom props", () => { it("should support custom props", () => {
render( render(
<RadioGroup data-testid="radio-group" label="Radio Group Label"> <RadioGroup data-testid="t--radio-group" label="Radio Group Label">
<Radio value="value-1">Value 1</Radio> <Radio value="value-1">Value 1</Radio>
<Radio value="value-2">Value 2</Radio> <Radio value="value-2">Value 2</Radio>
<Radio value="value-3">Value 3</Radio> <Radio value="value-3">Value 3</Radio>
</RadioGroup>, </RadioGroup>,
); );
const radioGroup = screen.getByTestId("radio-group"); const radioGroup = screen.getByTestId("t--radio-group");
expect(radioGroup).toBeInTheDocument(); expect(radioGroup).toBeInTheDocument();
}); });
@ -66,7 +67,7 @@ describe("@design-system/widgets/RadioGroup", () => {
expect(options[1]).not.toBeChecked(); expect(options[1]).not.toBeChecked();
}); });
it("should be able to fire onChange event", () => { it("should be able to fire onChange event", async () => {
const onChangeSpy = jest.fn(); const onChangeSpy = jest.fn();
render( render(
@ -77,7 +78,7 @@ describe("@design-system/widgets/RadioGroup", () => {
); );
const options = screen.getAllByRole("radio"); const options = screen.getAllByRole("radio");
userEvent.click(options[0]); await userEvent.click(options[0]);
expect(onChangeSpy).toHaveBeenCalled(); expect(onChangeSpy).toHaveBeenCalled();
}); });

View File

@ -12,9 +12,10 @@ describe("@design-system/widgets/Text", () => {
}); });
it("should support custom props", () => { it("should support custom props", () => {
const { container } = render(<Text data-testid="text">My Text</Text>); const { container } = render(<Text data-testid="t--text">My Text</Text>);
// eslint-disable-next-line testing-library/no-container,testing-library/no-node-access
const text = container.querySelector("div") as HTMLElement; const text = container.querySelector("div") as HTMLElement;
expect(text).toHaveAttribute("data-testid", "text"); expect(text).toHaveAttribute("data-testid", "t--text");
}); });
}); });

View File

@ -4,6 +4,7 @@
"rules": { "rules": {
"@typescript-eslint/strict-boolean-expressions": "off", "@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/prefer-nullish-coalescing": "off" "@typescript-eslint/prefer-nullish-coalescing": "off",
"testing-library/no-debugging-utils": "off"
} }
} }

View File

@ -4,6 +4,7 @@
"rules": { "rules": {
"@typescript-eslint/prefer-nullish-coalescing": "off", "@typescript-eslint/prefer-nullish-coalescing": "off",
"@typescript-eslint/strict-boolean-expressions": "off", "@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/no-explicit-any": "off" "@typescript-eslint/no-explicit-any": "off",
"testing-library/no-debugging-utils": "off"
} }
} }

View File

@ -8,6 +8,7 @@ describe("<AutoResizeTextArea />", () => {
describe("when autoResize is true", () => { describe("when autoResize is true", () => {
it("it should render a proxy textarea", async () => { it("it should render a proxy textarea", async () => {
const tree = renderer.create(<AutoResizeTextArea autoResize />); const tree = renderer.create(<AutoResizeTextArea autoResize />);
// eslint-disable-next-line testing-library/await-async-queries
expect(tree.root.findAllByType("textarea").length).toBe(2); expect(tree.root.findAllByType("textarea").length).toBe(2);
}); });
}); });
@ -15,6 +16,7 @@ describe("<AutoResizeTextArea />", () => {
describe("when autoResize is false", () => { describe("when autoResize is false", () => {
it("it should not render a proxy textarea if autoResize is false", async () => { it("it should not render a proxy textarea if autoResize is false", async () => {
const tree = renderer.create(<AutoResizeTextArea autoResize={false} />); const tree = renderer.create(<AutoResizeTextArea autoResize={false} />);
// eslint-disable-next-line testing-library/await-async-queries
expect(tree.root.findAllByType("textarea").length).toBe(1); expect(tree.root.findAllByType("textarea").length).toBe(1);
}); });
}); });

View File

@ -39,6 +39,7 @@ describe("CodeEditor", () => {
); );
const testInstance = testRenderer.root; const testInstance = testRenderer.root;
expect( expect(
// eslint-disable-next-line testing-library/await-async-queries
testInstance.findByType(EvaluatedValuePopup).props.hideEvaluatedValue, testInstance.findByType(EvaluatedValuePopup).props.hideEvaluatedValue,
).toBe(false); ).toBe(false);
}); });
@ -67,6 +68,7 @@ describe("CodeEditor", () => {
); );
const testInstance = testRenderer.root; const testInstance = testRenderer.root;
expect( expect(
// eslint-disable-next-line testing-library/await-async-queries
testInstance.findByType(EvaluatedValuePopup).props.hideEvaluatedValue, testInstance.findByType(EvaluatedValuePopup).props.hideEvaluatedValue,
).toBe(true); ).toBe(true);
}); });

View File

@ -38,9 +38,9 @@ describe("<CodeEditor /> - Keyboard navigation", () => {
</Provider> </Provider>
); );
it("Pressing tab should focus the component", () => { it("Pressing tab should focus the component", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.getByTestId("code-editor-target")).toHaveFocus(); expect(screen.getByTestId("code-editor-target")).toHaveFocus();
}); });
}); });

View File

@ -56,7 +56,10 @@ describe("EditorContextProvider", () => {
); );
const testInstance = testRenderer.root; const testInstance = testRenderer.root;
const result = ( const result = (
Object.keys(testInstance.findByType(TestChild).props.editorContext) || [] Object.keys(
// eslint-disable-next-line testing-library/await-async-queries
testInstance.findByType(TestChild).props.editorContext,
) || []
).sort(); ).sort();
expect(result).toEqual(expectedMethods); expect(result).toEqual(expectedMethods);
@ -92,7 +95,10 @@ describe("EditorContextProvider", () => {
); );
const testInstance = testRenderer.root; const testInstance = testRenderer.root;
const result = ( const result = (
Object.keys(testInstance.findByType(TestChild).props.editorContext) || [] Object.keys(
// eslint-disable-next-line testing-library/await-async-queries
testInstance.findByType(TestChild).props.editorContext,
) || []
).sort(); ).sort();
expect(result).toEqual(expectedMethods); expect(result).toEqual(expectedMethods);

View File

@ -4,7 +4,7 @@ import DynamicInputTextControl from "./DynamicInputTextControl";
import { reduxForm } from "redux-form"; import { reduxForm } from "redux-form";
import { mockCodemirrorRender } from "test/__mocks__/CodeMirrorEditorMock"; import { mockCodemirrorRender } from "test/__mocks__/CodeMirrorEditorMock";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { waitFor } from "@testing-library/dom"; import { waitFor } from "@testing-library/react";
function TestForm(props: any) { function TestForm(props: any) {
return <div>{props.children}</div>; return <div>{props.children}</div>;
@ -17,6 +17,7 @@ const ReduxFormDecorator = reduxForm({
describe("DynamicInputTextControl", () => { describe("DynamicInputTextControl", () => {
beforeEach(() => { beforeEach(() => {
// eslint-disable-next-line testing-library/no-render-in-lifecycle
mockCodemirrorRender(); mockCodemirrorRender();
}); });
it("renders correctly", () => { it("renders correctly", () => {
@ -38,10 +39,13 @@ describe("DynamicInputTextControl", () => {
{}, {},
); );
// eslint-disable-next-line testing-library/await-async-utils
waitFor(async () => { waitFor(async () => {
const input = screen.getAllByText("My test value")[0]; const input = screen.getAllByText("My test value")[0];
userEvent.type(input, "New text"); // eslint-disable-next-line testing-library/no-wait-for-side-effects
await userEvent.type(input, "New text");
await expect(screen.getAllByText("New text")).toHaveLength(2); await expect(screen.getAllByText("New text")).toHaveLength(2);
// eslint-disable-next-line testing-library/await-async-queries
await expect(screen.findByText("My test value")).toBeNull(); await expect(screen.findByText("My test value")).toBeNull();
}); });
}); });

View File

@ -82,67 +82,67 @@ describe("<ColorPicker />", () => {
}); });
describe("<ColorPicker /> - Keyboard Navigation", () => { describe("<ColorPicker /> - Keyboard Navigation", () => {
it("Pressing tab should focus the component", () => { it("Pressing tab should focus the component", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.getByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}); });
it("Pressing {Enter} should open the colorpicker", () => { it("Pressing {Enter} should open the colorpicker", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.queryByTestId("color-picker")).toBeNull(); expect(screen.queryByTestId("color-picker")).toBeNull();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(screen.queryByTestId("color-picker")).toBeInTheDocument(); expect(screen.getByTestId("color-picker")).toBeInTheDocument();
}); });
it("Pressing {Escape} should close the colorpicker", async () => { it("Pressing {Escape} should close the colorpicker", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.queryByTestId("color-picker")).toBeNull(); expect(screen.queryByTestId("color-picker")).toBeNull();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(screen.queryByTestId("color-picker")).toBeInTheDocument(); expect(screen.getByTestId("color-picker")).toBeInTheDocument();
userEvent.keyboard("{Escape}"); await userEvent.keyboard("{Escape}");
await waitForElementToBeRemoved(screen.queryByTestId("color-picker")); await waitForElementToBeRemoved(screen.queryByTestId("color-picker"));
}); });
it("Pressing {Tab} should shift sections in the colorpicker", () => { it("Pressing {Tab} should shift sections in the colorpicker", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[0], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[0],
).toHaveFocus(); ).toHaveFocus();
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1],
).toHaveFocus(); ).toHaveFocus();
// Back to first color // Back to first color
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[0], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[0],
).toHaveFocus(); ).toHaveFocus();
}); });
it("Pressing {ArrowRight} should shift focus to color to the right", () => { it("Pressing {ArrowRight} should shift focus to color to the right", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1],
).toHaveFocus(); ).toHaveFocus();
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1] document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1]
@ -150,76 +150,76 @@ describe("<ColorPicker /> - Keyboard Navigation", () => {
).toHaveFocus(); ).toHaveFocus();
}); });
it("Pressing {ArrowLeft} should shift focus to color to the left", () => { it("Pressing {ArrowLeft} should shift focus to color to the left", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1],
).toHaveFocus(); ).toHaveFocus();
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1] document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1]
.parentElement?.childNodes[2], .parentElement?.childNodes[2],
).toHaveFocus(); ).toHaveFocus();
userEvent.keyboard("{ArrowLeft}"); await userEvent.keyboard("{ArrowLeft}");
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1] document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1]
.parentElement?.childNodes[1], .parentElement?.childNodes[1],
).toHaveFocus(); ).toHaveFocus();
}); });
it("Pressing {ArrowDown} should shift focus to color to the bottom", () => { it("Pressing {ArrowDown} should shift focus to color to the bottom", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1],
).toHaveFocus(); ).toHaveFocus();
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1] document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1]
.parentElement?.childNodes[10], .parentElement?.childNodes[10],
).toHaveFocus(); ).toHaveFocus();
}); });
it("Pressing {ArrowUp} should shift focus to color to the top", () => { it("Pressing {ArrowUp} should shift focus to color to the top", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1], document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1],
).toHaveFocus(); ).toHaveFocus();
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1] document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1]
.parentElement?.childNodes[21], .parentElement?.childNodes[21],
).toHaveFocus(); ).toHaveFocus();
userEvent.keyboard("{ArrowUp}"); await userEvent.keyboard("{ArrowUp}");
expect( expect(
document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1] document.querySelectorAll("[tabindex='0'].t--colorpicker-v2-color")[1]
.parentElement?.childNodes[11], .parentElement?.childNodes[11],
@ -229,12 +229,12 @@ describe("<ColorPicker /> - Keyboard Navigation", () => {
it("Pressing {Enter} should select the color in focus", async () => { it("Pressing {Enter} should select the color in focus", async () => {
const onColorChange = jest.fn(); const onColorChange = jest.fn();
render(getTestComponent(onColorChange)); render(getTestComponent(onColorChange));
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
userEvent.tab(); await userEvent.tab();
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(onColorChange).toBeCalled(); expect(onColorChange).toBeCalled();
await waitForElementToBeRemoved(screen.queryByTestId("color-picker")); await waitForElementToBeRemoved(screen.queryByTestId("color-picker"));
}); });

View File

@ -46,9 +46,9 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
/> />
); );
it("Pressing tab should focus the component", () => { it("Pressing tab should focus the component", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.getByRole("button")).toHaveFocus(); expect(screen.getByRole("button")).toHaveFocus();
}); });
@ -56,53 +56,53 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
"Pressing '%s' should open the icon selector", "Pressing '%s' should open the icon selector",
async (key) => { async (key) => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.queryByRole("list")).toBeNull(); expect(screen.queryByRole("list")).toBeNull();
userEvent.keyboard(key); await userEvent.keyboard(key);
expect(screen.queryByRole("list")).toBeInTheDocument(); expect(screen.getByRole("list")).toBeInTheDocument();
// Makes sure search bar is having focus // Makes sure search bar is having focus
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
}, },
); );
it("Pressing '{Escape}' should close the icon selector", async () => { it("Pressing '{Escape}' should close the icon selector", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.queryByRole("list")).toBeNull(); expect(screen.queryByRole("list")).toBeNull();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(screen.queryByRole("list")).toBeInTheDocument(); expect(screen.getByRole("list")).toBeInTheDocument();
userEvent.keyboard("{Escape}"); await userEvent.keyboard("{Escape}");
await waitForElementToBeRemoved(screen.getAllByRole("list")); await waitForElementToBeRemoved(screen.queryByRole("list"));
}); });
it("Pressing '{ArrowDown}' while search is in focus should remove the focus", async () => { it("Pressing '{ArrowDown}' while search is in focus should remove the focus", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(screen.queryByRole("list")).toBeInTheDocument(); expect(screen.getByRole("list")).toBeInTheDocument();
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
expect(screen.queryByRole("textbox")).not.toHaveFocus(); expect(screen.getByRole("textbox")).not.toHaveFocus();
}); });
it("Pressing '{Shift} + {ArrowUp}' while search is not in focus should focus search box", async () => { it("Pressing '{Shift} + {ArrowUp}' while search is not in focus should focus search box", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(screen.queryByRole("list")).toBeInTheDocument(); expect(screen.getByRole("list")).toBeInTheDocument();
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
expect(screen.queryByRole("textbox")).not.toHaveFocus(); expect(screen.getByRole("textbox")).not.toHaveFocus();
userEvent.keyboard("{Shift}{ArrowUp}"); await userEvent.keyboard("{Shift}{ArrowUp}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
}); });
@ -115,18 +115,18 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
*/ */
it("Pressing '{ArrowDown}' should navigate the icon selection downwards", async () => { it("Pressing '{ArrowDown}' should navigate the icon selection downwards", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
// used to shift the focus from search // used to shift the focus from search
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
@ -134,25 +134,25 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
it("Pressing '{ArrowUp}' should navigate the icon selection upwards", async () => { it("Pressing '{ArrowUp}' should navigate the icon selection upwards", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
// used to shift the focus from search // used to shift the focus from search
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
userEvent.keyboard("{ArrowUp}"); await userEvent.keyboard("{ArrowUp}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
@ -160,18 +160,18 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
it("Pressing '{ArrowRight}' should navigate the icon selection towards right", async () => { it("Pressing '{ArrowRight}' should navigate the icon selection towards right", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
// used to shift the focus from search // used to shift the focus from search
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
@ -179,25 +179,25 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
it("Pressing '{ArrowLeft}' should navigate the icon selection towards left", async () => { it("Pressing '{ArrowLeft}' should navigate the icon selection towards left", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
// used to shift the focus from search // used to shift the focus from search
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
userEvent.keyboard("{ArrowLeft}"); await userEvent.keyboard("{ArrowLeft}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
@ -206,41 +206,39 @@ describe("<IconSelectControl /> - Keyboard navigation", () => {
it("Pressing '{Enter}' or ' ' should select the icon", async () => { it("Pressing '{Enter}' or ' ' should select the icon", async () => {
const handleOnSelect = jest.fn(); const handleOnSelect = jest.fn();
render(getTestComponent(handleOnSelect)); render(getTestComponent(handleOnSelect));
userEvent.tab(); await userEvent.tab();
expect(screen.queryByRole("button")?.textContent).toEqual( expect(screen.getByRole("button")?.textContent).toEqual("(none)caret-down");
"(none)caret-down", await userEvent.keyboard("{Enter}");
);
userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
// used to shift the focus from search // used to shift the focus from search
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
userEvent.keyboard(" "); await userEvent.keyboard(" ");
expect(handleOnSelect).toHaveBeenCalledTimes(1); expect(handleOnSelect).toHaveBeenCalledTimes(1);
expect(handleOnSelect.mock.calls[0]).toMatchSnapshot(); expect(handleOnSelect.mock.calls[0]).toMatchSnapshot();
await waitForElementToBeRemoved(screen.getByRole("list")); await waitForElementToBeRemoved(screen.queryByRole("list"));
userEvent.keyboard("{Enter}"); await userEvent.keyboard("{Enter}");
expect(screen.queryByRole("list")).toBeInTheDocument(); expect(screen.getByRole("list")).toBeInTheDocument();
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
).toMatchSnapshot(); ).toMatchSnapshot();
userEvent.keyboard("{ArrowDown}"); await userEvent.keyboard("{ArrowDown}");
userEvent.keyboard("{ArrowRight}"); await userEvent.keyboard("{ArrowRight}");
userEvent.keyboard(" "); await userEvent.keyboard(" ");
expect(handleOnSelect).toHaveBeenCalledTimes(2); expect(handleOnSelect).toHaveBeenCalledTimes(2);
expect(handleOnSelect.mock.calls[1]).toMatchSnapshot(); expect(handleOnSelect.mock.calls[1]).toMatchSnapshot();
}); });
@ -269,13 +267,11 @@ describe("<IconSelectControl /> - (none) icon", () => {
it("Should display (none) icon when hideNoneIcon property is false/undefined", async () => { it("Should display (none) icon when hideNoneIcon property is false/undefined", async () => {
render(getTestComponent()); render(getTestComponent());
userEvent.tab(); await userEvent.tab();
expect(screen.queryByRole("button")?.textContent).toEqual( expect(screen.getByRole("button")?.textContent).toEqual("(none)caret-down");
"(none)caret-down", await userEvent.keyboard("{Enter}");
);
userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,
@ -287,13 +283,11 @@ describe("<IconSelectControl /> - (none) icon", () => {
it("Should not display (none) icon when hideNoneIcon property is true", async () => { it("Should not display (none) icon when hideNoneIcon property is true", async () => {
render(getTestComponent(true)); render(getTestComponent(true));
userEvent.tab(); await userEvent.tab();
expect(screen.queryByRole("button")?.textContent).toEqual( expect(screen.getByRole("button")?.textContent).toEqual("(none)caret-down");
"(none)caret-down", await userEvent.keyboard("{Enter}");
);
userEvent.keyboard("{Enter}");
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole("textbox")).toHaveFocus(); expect(screen.getByRole("textbox")).toHaveFocus();
}, waitForParamsForSearchFocus); }, waitForParamsForSearchFocus);
expect( expect(
document.querySelector("a.bp3-active")?.children[0].classList, document.querySelector("a.bp3-active")?.children[0].classList,

View File

@ -40,6 +40,7 @@ describe("DragLayerComponent", () => {
); );
const testInstance = testRenderer.root; const testInstance = testRenderer.root;
// eslint-disable-next-line testing-library/await-async-queries
expect(testInstance.findByType(DragLayerComponent).props.noPad).toBe(true); expect(testInstance.findByType(DragLayerComponent).props.noPad).toBe(true);
}); });
}); });

View File

@ -83,6 +83,6 @@ describe("Accordion", () => {
expect(document.querySelector("[name='expand-more']")).toBeDefined(); expect(document.querySelector("[name='expand-more']")).toBeDefined();
document.querySelector("hr")?.click(); document.querySelector("hr")?.click();
expect(document.querySelector("[name='expand-less']")).toBeDefined(); expect(document.querySelector("[name='expand-less']")).toBeDefined();
expect(screen.queryByTestId("admin-settings-group-wrapper")).toBeDefined(); expect(screen.getByTestId("admin-settings-group-wrapper")).toBeDefined();
}); });
}); });

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { render, screen, cleanup } from "@testing-library/react"; import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect"; import "@testing-library/jest-dom/extend-expect";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { ThemeProvider } from "styled-components"; import { ThemeProvider } from "styled-components";
@ -155,8 +155,6 @@ export const fetchApplicationMockResponse = {
}; };
describe("App viewer fork button", () => { describe("App viewer fork button", () => {
afterEach(cleanup);
it("Fork modal trigger should not be displayed until user details are fetched", () => { it("Fork modal trigger should not be displayed until user details are fetched", () => {
render( render(
<Provider store={getStore()}> <Provider store={getStore()}>

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { render, screen, fireEvent, cleanup } from "@testing-library/react"; import { render, screen, fireEvent } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect"; import "@testing-library/jest-dom/extend-expect";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import store from "store"; import store from "store";
@ -48,7 +48,6 @@ describe("Contains all UI tests for JS libraries", () => {
type: ReduxActionTypes.TOGGLE_INSTALLER, type: ReduxActionTypes.TOGGLE_INSTALLER,
payload: true, payload: true,
}); });
afterEach(cleanup);
it("Headers should exist", () => { it("Headers should exist", () => {
render( render(
@ -80,7 +79,7 @@ describe("Contains all UI tests for JS libraries", () => {
expect(screen.getByTestId("install-library-btn")).toBeEnabled(); expect(screen.getByTestId("install-library-btn")).toBeEnabled();
expect(screen.queryByText("Please enter a valid URL")).toBeNull(); expect(screen.queryByText("Please enter a valid URL")).toBeNull();
fireEvent.change(input, { target: { value: "23" } }); fireEvent.change(input, { target: { value: "23" } });
expect(screen.queryByText("Please enter a valid URL")).toBeDefined(); expect(screen.getByText("Please enter a valid URL")).toBeDefined();
expect(screen.getByTestId("install-library-btn")).toBeDisabled(); expect(screen.getByTestId("install-library-btn")).toBeDisabled();
}); });
@ -113,6 +112,7 @@ describe("Contains all UI tests for JS libraries", () => {
fireEvent.click(installButton); fireEvent.click(installButton);
expect( expect(
// eslint-disable-next-line testing-library/prefer-presence-queries
screen.queryByText( screen.queryByText(
`Installing library for ${fetchApplicationMockResponse.data.application.name}`, `Installing library for ${fetchApplicationMockResponse.data.application.name}`,
), ),
@ -136,6 +136,7 @@ describe("Contains all UI tests for JS libraries", () => {
}); });
expect( expect(
// eslint-disable-next-line testing-library/prefer-presence-queries
screen.queryByText( screen.queryByText(
`Installing library for ${fetchApplicationMockResponse.data.application.name}`, `Installing library for ${fetchApplicationMockResponse.data.application.name}`,
), ),

View File

@ -268,7 +268,7 @@ describe("Cut/Copy/Paste hotkey", () => {
</MockPageDSL>, </MockPageDSL>,
{ initialState: store.getState(), sagasToRun: sagasToRunForTests }, { initialState: store.getState(), sagasToRun: sagasToRunForTests },
); );
const artBoard: any = await component.queryByTestId("t--canvas-artboard"); const artBoard: any = component.queryByTestId("t--canvas-artboard");
// deselect all other widgets // deselect all other widgets
fireEvent.click(artBoard); fireEvent.click(artBoard);
act(() => { act(() => {
@ -358,7 +358,7 @@ describe("Cut/Copy/Paste hotkey", () => {
</GlobalHotKeys> </GlobalHotKeys>
</MockPageDSL>, </MockPageDSL>,
); );
const artBoard: any = await component.queryByTestId("t--canvas-artboard"); const artBoard: any = component.queryByTestId("t--canvas-artboard");
// deselect all other widgets // deselect all other widgets
fireEvent.click(artBoard); fireEvent.click(artBoard);
act(() => { act(() => {

View File

@ -23,7 +23,7 @@ const FileTabs = (props: Props) => {
const currentEntity = identifyEntityFromPath(location.pathname); const currentEntity = identifyEntityFromPath(location.pathname);
return ( return (
<Flex data-test-id="editor-tabs" flex="1" gap="spaces-2" height="100%"> <Flex data-testid="editor-tabs" flex="1" gap="spaces-2" height="100%">
{tabs.map((tab: EntityItem) => ( {tabs.map((tab: EntityItem) => (
<StyledTab <StyledTab
className={clsx( className={clsx(

View File

@ -9,9 +9,9 @@ import { lightTheme } from "selectors/themeSelectors";
import store from "store"; import store from "store";
import { MainContainerWidthToggles } from "./MainContainerWidthToggles"; import { MainContainerWidthToggles } from "./MainContainerWidthToggles";
function navigateWithArrowKeys(key: string, noOfPresses: number) { async function navigateWithArrowKeys(key: string, noOfPresses: number) {
for (let i = 0; i < noOfPresses; i++) { for (let i = 0; i < noOfPresses; i++) {
userEvent.keyboard(key); await userEvent.keyboard(key);
} }
} }
@ -24,9 +24,9 @@ describe("<MainContainerWidthToggles />", () => {
</ThemeProvider> </ThemeProvider>
); );
it("Pressing tab should focus on the first component", () => { it("Pressing tab should focus on the first component", async () => {
const { container } = render(getTestComponent()); const { container } = render(getTestComponent());
userEvent.tab(); await userEvent.tab();
// Should focus on the first component // Should focus on the first component
const tab = container.getElementsByClassName( const tab = container.getElementsByClassName(
@ -35,21 +35,21 @@ describe("<MainContainerWidthToggles />", () => {
expect(tab).toHaveFocus(); expect(tab).toHaveFocus();
}); });
it("{ArrowRight} should focus the next item", () => { it("{ArrowRight} should focus the next item", async () => {
const { container } = render(getTestComponent()); const { container } = render(getTestComponent());
const tabs = container.getElementsByClassName( const tabs = container.getElementsByClassName(
"ads-v2-segmented-control__segments-container", "ads-v2-segmented-control__segments-container",
); );
userEvent.tab(); await userEvent.tab();
navigateWithArrowKeys("{ArrowRight}", 1); await navigateWithArrowKeys("{ArrowRight}", 1);
expect(tabs[1]).toHaveFocus(); expect(tabs[1]).toHaveFocus();
// Focus back on the first element // Focus back on the first element
userEvent.keyboard("{ArrowLeft}"); await userEvent.keyboard("{ArrowLeft}");
// Arrow Right after the last item should focus the first item again // Arrow Right after the last item should focus the first item again
navigateWithArrowKeys("{ArrowRight}", tabs.length); await navigateWithArrowKeys("{ArrowRight}", tabs.length);
expect(tabs[0]).toHaveFocus(); expect(tabs[0]).toHaveFocus();
}); });
@ -59,13 +59,13 @@ describe("<MainContainerWidthToggles />", () => {
"ads-v2-segmented-control__segments-container", "ads-v2-segmented-control__segments-container",
); );
userEvent.tab(); await userEvent.tab();
// Arrow Left on the First item should focus on the last item // Arrow Left on the First item should focus on the last item
navigateWithArrowKeys("{ArrowLeft}", 1); await navigateWithArrowKeys("{ArrowLeft}", 1);
expect(tabs[tabs.length - 1]).toHaveFocus(); expect(tabs[tabs.length - 1]).toHaveFocus();
navigateWithArrowKeys("{ArrowLeft}", tabs.length - 1); await navigateWithArrowKeys("{ArrowLeft}", tabs.length - 1);
expect(tabs[0]).toHaveFocus(); expect(tabs[0]).toHaveFocus();
}); });

View File

@ -64,11 +64,11 @@ const renderComponent = (store: MockStoreEnhanced<unknown, any>) => {
describe("Git Settings Modal", () => { describe("Git Settings Modal", () => {
it("is rendered properly", () => { it("is rendered properly", () => {
const store = mockStore(createInitialState()); const store = mockStore(createInitialState());
const { queryByTestId } = renderComponent(store); const { getByTestId } = renderComponent(store);
expect(queryByTestId("t--git-settings-modal")).toBeTruthy(); expect(getByTestId("t--git-settings-modal")).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.GENERAL}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.GENERAL}`)).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.BRANCH}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.BRANCH}`)).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.CD}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.CD}`)).toBeTruthy();
}); });
it("is not rendering branch tab when neither of the features are enabled", () => { it("is not rendering branch tab when neither of the features are enabled", () => {
@ -81,11 +81,11 @@ describe("Git Settings Modal", () => {
return newState; return newState;
}); });
const store = mockStore(initialState); const store = mockStore(initialState);
const { queryByTestId } = renderComponent(store); const { getByTestId, queryByTestId } = renderComponent(store);
expect(queryByTestId("t--git-settings-modal")).toBeTruthy(); expect(getByTestId("t--git-settings-modal")).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.GENERAL}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.GENERAL}`)).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.BRANCH}`)).not.toBeTruthy(); expect(queryByTestId(`t--tab-${GitSettingsTab.BRANCH}`)).not.toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.CD}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.CD}`)).toBeTruthy();
}); });
it("is not rendering CD when feature flag is not enabled", () => { it("is not rendering CD when feature flag is not enabled", () => {
@ -98,10 +98,10 @@ describe("Git Settings Modal", () => {
return newState; return newState;
}); });
const store = mockStore(initialState); const store = mockStore(initialState);
const { queryByTestId } = renderComponent(store); const { getByTestId, queryByTestId } = renderComponent(store);
expect(queryByTestId("t--git-settings-modal")).toBeTruthy(); expect(getByTestId("t--git-settings-modal")).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.GENERAL}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.GENERAL}`)).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.BRANCH}`)).toBeTruthy(); expect(getByTestId(`t--tab-${GitSettingsTab.BRANCH}`)).toBeTruthy();
expect(queryByTestId(`t--tab-${GitSettingsTab.CD}`)).not.toBeTruthy(); expect(queryByTestId(`t--tab-${GitSettingsTab.CD}`)).not.toBeTruthy();
}); });
}); });

View File

@ -5,7 +5,7 @@ import React from "react";
describe("BranchButton", () => { describe("BranchButton", () => {
it("renders properly", async () => { it("renders properly", async () => {
render(<BranchButton />); render(<BranchButton />);
const currentBranch = await screen.queryByTestId( const currentBranch = screen.queryByTestId(
"t--branch-button-currentBranch", "t--branch-button-currentBranch",
); );
expect(currentBranch?.innerHTML).toContain("*"); expect(currentBranch?.innerHTML).toContain("*");

View File

@ -39,18 +39,16 @@ jest.mock("react-redux", () => {
describe("Connection Success Modal", () => { describe("Connection Success Modal", () => {
it("is rendered properly", () => { it("is rendered properly", () => {
const store = mockStore(initialState); const store = mockStore(initialState);
const { queryByTestId } = render( const { getByTestId } = render(
<Provider store={store}> <Provider store={store}>
<ConnectionSuccess /> <ConnectionSuccess />
</Provider>, </Provider>,
); );
expect(queryByTestId("t--git-success-modal-body")).toBeTruthy(); expect(getByTestId("t--git-success-modal-body")).toBeTruthy();
expect( expect(
queryByTestId("t--git-success-modal-start-using-git-cta"), getByTestId("t--git-success-modal-start-using-git-cta"),
).toBeTruthy();
expect(
queryByTestId("t--git-success-modal-open-settings-cta"),
).toBeTruthy(); ).toBeTruthy();
expect(getByTestId("t--git-success-modal-open-settings-cta")).toBeTruthy();
}); });
it("go to settings cta button is working", () => { it("go to settings cta button is working", () => {

View File

@ -6,7 +6,7 @@ import "jest-styled-components";
describe("BetaTag", () => { describe("BetaTag", () => {
it("renders properly", async () => { it("renders properly", async () => {
render(<BetaTag />); render(<BetaTag />);
const actual = await screen.queryByTestId("t--beta-tag"); const actual = screen.queryByTestId("t--beta-tag");
// renders // renders
expect(actual).not.toBeNull(); expect(actual).not.toBeNull();

View File

@ -13,15 +13,15 @@ describe("ConflictInfo", () => {
// check for existence // check for existence
[ [
await screen.queryByTestId("t--conflict-info-container"), screen.queryByTestId("t--conflict-info-container"),
await screen.queryByTestId("t--conflict-info-error-warning"), screen.queryByTestId("t--conflict-info-error-warning"),
].every((query) => { ].every((query) => {
expect(query).not.toBeNull(); expect(query).not.toBeNull();
return true; return true;
}); });
//check for text //check for text
const container = await screen.getByTestId("t--conflict-info-container"); const container = screen.getByTestId("t--conflict-info-container");
const html = container.innerHTML.toString(); const html = container.innerHTML.toString();
expect(html.includes("Learn more")).toBeTruthy(); expect(html.includes("Learn more")).toBeTruthy();
expect(html.includes("Open repository")).toBeTruthy(); expect(html.includes("Open repository")).toBeTruthy();

View File

@ -6,7 +6,7 @@ import "jest-styled-components";
describe("DefaultTag", () => { describe("DefaultTag", () => {
it("renders properly", async () => { it("renders properly", async () => {
render(<DefaultTag />); render(<DefaultTag />);
const actual = await screen.queryByTestId("t--default-tag"); const actual = screen.queryByTestId("t--default-tag");
// renders // renders
expect(actual).not.toBeNull(); expect(actual).not.toBeNull();

View File

@ -7,7 +7,7 @@ describe("RemoteBranchList", function () {
it("renders nothing when param:remoteBranches is an empty array", async () => { it("renders nothing when param:remoteBranches is an empty array", async () => {
render(RemoteBranchList([], () => undefined)); render(RemoteBranchList([], () => undefined));
const renderedList = await screen.queryByTestId( const renderedList = screen.queryByTestId(
"t--git-remote-branch-list-container", "t--git-remote-branch-list-container",
); );
expect(renderedList?.innerHTML).toBeFalsy(); expect(renderedList?.innerHTML).toBeFalsy();
@ -24,7 +24,7 @@ describe("RemoteBranchList", function () {
expect(renderedList?.children.length).toEqual(2); expect(renderedList?.children.length).toEqual(2);
// contains styled segment header // contains styled segment header
const header = await screen.queryByTestId("t--branch-list-header-local"); const header = screen.queryByTestId("t--branch-list-header-local");
expect(header).not.toBeNull(); expect(header).not.toBeNull();
expect(header?.innerHTML.includes("Remote branches")).toBeTruthy(); expect(header?.innerHTML.includes("Remote branches")).toBeTruthy();
}); });

View File

@ -9,17 +9,17 @@ function renderComponent() {
} }
describe("SetupForm", () => { describe("SetupForm", () => {
it("If the form is in invalid state pressing enter should not submit the form", () => { it("If the form is in invalid state pressing enter should not submit the form", async () => {
renderComponent(); renderComponent();
const verifyPassword = screen.getByTestId("verifyPassword"); const verifyPassword = screen.getByTestId("verifyPassword");
const formPage = screen.getByTestId("formPage"); const formPage = screen.getByTestId("formPage");
expect(verifyPassword).toHaveAttribute("name"); expect(verifyPassword).toHaveAttribute("name");
userEvent.keyboard("{enter}"); await userEvent.keyboard("{enter}");
// This attribute is removed in onsubmit // This attribute is removed in onsubmit
expect(verifyPassword).toHaveAttribute("name"); expect(verifyPassword).toHaveAttribute("name");
expect(formPage).toHaveClass("block"); expect(formPage).toHaveClass("block");
}); });
it("If the form is in valid state pressing enter should nagivate to next page", () => { it("If the form is in valid state pressing enter should nagivate to next page", async () => {
renderComponent(); renderComponent();
const formPage = screen.getByTestId("formPage"); const formPage = screen.getByTestId("formPage");
expect(formPage).toHaveClass("block"); expect(formPage).toHaveClass("block");
@ -33,7 +33,7 @@ describe("SetupForm", () => {
fireEvent.change(password, { target: { value: "Test@123" } }); fireEvent.change(password, { target: { value: "Test@123" } });
const verifyPassword = screen.getByTestId("verifyPassword"); const verifyPassword = screen.getByTestId("verifyPassword");
fireEvent.change(verifyPassword, { target: { value: "Test@123" } }); fireEvent.change(verifyPassword, { target: { value: "Test@123" } });
userEvent.keyboard("{enter}"); await userEvent.keyboard("{enter}");
expect(formPage).toHaveClass("hidden"); expect(formPage).toHaveClass("hidden");
}); });
}); });

View File

@ -234,7 +234,7 @@ describe("Chart Widget", () => {
expect(mockCallback.mock.calls.length).toEqual(0); expect(mockCallback.mock.calls.length).toEqual(0);
const el = await screen.findByText("1000"); const el = await screen.findByText("1000");
userEvent.click(el); await userEvent.click(el);
expect(mockCallback.mock.calls.length).toEqual(1); expect(mockCallback.mock.calls.length).toEqual(1);
}); });
}); });

View File

@ -86,14 +86,14 @@ describe("<DividerWidget />", () => {
} }
test("should render Divider widget horizontal by default", async () => { test("should render Divider widget horizontal by default", async () => {
const { queryByTestId } = renderDividerWidget(); const { getByTestId } = renderDividerWidget();
expect(queryByTestId("dividerHorizontal")).toBeTruthy(); expect(getByTestId("dividerHorizontal")).toBeTruthy();
}); });
test("should render Divider vertical", async () => { test("should render Divider vertical", async () => {
const { queryByTestId } = renderDividerWidget({ orientation: "vertical" }); const { getByTestId } = renderDividerWidget({ orientation: "vertical" });
expect(queryByTestId("dividerVertical")).toBeTruthy(); expect(getByTestId("dividerVertical")).toBeTruthy();
}); });
}); });

View File

@ -3,6 +3,7 @@ import {
widgetCanvasFactory, widgetCanvasFactory,
} from "test/factories/WidgetFactoryUtils"; } from "test/factories/WidgetFactoryUtils";
import { render, fireEvent } from "test/testUtils"; import { render, fireEvent } from "test/testUtils";
import { screen } from "@testing-library/react";
import * as widgetRenderUtils from "utils/widgetRenderUtils"; import * as widgetRenderUtils from "utils/widgetRenderUtils";
import * as dataTreeSelectors from "selectors/dataTreeSelectors"; import * as dataTreeSelectors from "selectors/dataTreeSelectors";
import * as editorSelectors from "selectors/editorSelectors"; import * as editorSelectors from "selectors/editorSelectors";
@ -30,13 +31,13 @@ describe("Tabs widget functional cases", () => {
const dsl: any = widgetCanvasFactory.build({ const dsl: any = widgetCanvasFactory.build({
children, children,
}); });
const component = render( render(
<MockPageDSL dsl={dsl}> <MockPageDSL dsl={dsl}>
<Canvas canvasWidth={dsl.rightColumn} widgetsStructure={dsl} /> <Canvas canvasWidth={dsl.rightColumn} widgetsStructure={dsl} />
</MockPageDSL>, </MockPageDSL>,
); );
const tab1 = component.queryByText("Tab 1"); const tab1 = screen.queryByText("Tab 1");
const tab2 = component.queryByText("Tab 2"); const tab2 = screen.queryByText("Tab 2");
expect(tab1).toBeDefined(); expect(tab1).toBeDefined();
expect(tab2).toBeDefined(); expect(tab2).toBeDefined();
}); });

View File

@ -12022,7 +12022,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.13.0, @typescript-eslint/utils@npm:^5.45.0": "@typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.13.0, @typescript-eslint/utils@npm:^5.45.0, @typescript-eslint/utils@npm:^5.58.0":
version: 5.62.0 version: 5.62.0
resolution: "@typescript-eslint/utils@npm:5.62.0" resolution: "@typescript-eslint/utils@npm:5.62.0"
dependencies: dependencies:
@ -13219,6 +13219,7 @@ __metadata:
eslint-plugin-react-hooks: ^4.6.0 eslint-plugin-react-hooks: ^4.6.0
eslint-plugin-sort-destructure-keys: ^1.5.0 eslint-plugin-sort-destructure-keys: ^1.5.0
eslint-plugin-storybook: ^0.6.15 eslint-plugin-storybook: ^0.6.15
eslint-plugin-testing-library: ^6.2.0
esm: ^3.2.25 esm: ^3.2.25
factory.ts: ^0.5.1 factory.ts: ^0.5.1
fast-deep-equal: ^3.1.3 fast-deep-equal: ^3.1.3
@ -18713,6 +18714,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-testing-library@npm:^6.2.0":
version: 6.2.0
resolution: "eslint-plugin-testing-library@npm:6.2.0"
dependencies:
"@typescript-eslint/utils": ^5.58.0
peerDependencies:
eslint: ^7.5.0 || ^8.0.0
checksum: 7af7e0a1eee44c6ba65ce2ae99f8e46ce709a319f4cce778bb0af2dda5828d78f3a81e8989c7b691a8b9b9fef102b56136209aac700038b9e64794600b0d12db
languageName: node
linkType: hard
"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1": "eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1":
version: 5.1.1 version: 5.1.1
resolution: "eslint-scope@npm:5.1.1" resolution: "eslint-scope@npm:5.1.1"