Skip to content

Commit

Permalink
Adds Checkbox Test Utils (#2290)
Browse files Browse the repository at this point in the history
* wip, adding getByLgId

* getError

* add comments

* wip, starting findBy

* test passing

* wip, importing from testing-lib-dom

* delete test harness from packages

* add back test-harness

* everything is broken

* what did I change to make this work?

* clean up

* add another test for findbylgid

* delete v1 of test harness

* remove more of v1 test harness

* remove comments

* update yarn

* remove line

* rename to test-harnesses

* rename testid.ts to lgid.ts

* update export

* add description

* add queryByLgId

* add changesets

* wip

* wip - added tests for textinput

* adds more test

* more tests

* add getByQuerySelector util

* add another test

* some more tests

* add getByQuerySelector util

* wip text area

* textArea tests

* toggle tests

* update text input tests

* cleaning up tests

* restructure files

* clean up comments

* more clean up

* icon changeset

* LGIdProps => LgIdProps

* lib changeset

* add changeset for inputs

* started READMEs

* add isOptional

* cs for test-harnesses

* fix cs

* remove ts-expect-error

* wip readme

* toggle readme

* wip, async tests

* update tests

* fix build error?

* testing

* rename dir

* testing

* fix icon

* fix changeset

* rename findByQuerySelector to queryByQuerySelector

* rename inputValue to getInputValue

* fix failing tests

* remove dom tests

* remove dup tests

* update toggle readme

* text input README

* fix README

* update READMEs

* test

* add lgid to `label` and `description`, move `isOptional` to `test-harnessess`

* update changelogs

* fix test-harnesses version and changeset

* include ticket

* update tests

* add constants for ids

* more ids

* rename test utils

* update READMEs

* add more test ids

* update constants

* remove src

* LG-4129: Select test harness (#2275)

* wip select test harnesses

* wip, adding tests

* adding more tests

* adding more tests

* comment

* adds more tests

* more tests

* update utils tests

* wip, tests

* select specs

* move popover data-lgid

* update types

* remove folder

* add select const

* add more ids

* readme

* update tests

* lint

* is this it?

* update changesets

* changesets

* caret, readmes

* update constants

* update changelogs

* typography changeset

* text input and text area combine utils

* update textInput, textArea, and Toggle utils

* fix build errors

* update getLGSelectTestUtils type

* add JSDoc to renderAsyncTest

* update util names

* remove act from toggle test

* queryByQuerySelector -> queryBySelector

* fix build error

* update LgIdProps type

* update select specs

* fix test?

* small updates

* checkbox test utils

* with changeset

* make changeset the same

* typo

* solve another problem

* update changelog

* with Adams feedback

* and update the readme

* run fix

* with button too

* with yarn fix

* try again r17

* update table tests

* with return types

* attempt to fix things

* change log

* responding to PR feedback

* tests and docs

* add type test

* fix tests

* compat

* a few more tests

* responding to PR feedback

---------

Co-authored-by: Shaneeza <[email protected]>
  • Loading branch information
bruugey and shaneeza authored Apr 8, 2024
1 parent 1d55530 commit 1ec45a7
Show file tree
Hide file tree
Showing 26 changed files with 736 additions and 51 deletions.
5 changes: 5 additions & 0 deletions .changeset/gorgeous-buckets-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/table': patch
---

Updates internal test suite
10 changes: 10 additions & 0 deletions .changeset/green-hotels-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@leafygreen-ui/button': minor
---


- Exports `getTestUtils`, a util to reliably interact with `LG Button` in a product test suite. For more details, check out the [README](https://github.com/mongodb/leafygreen-ui/tree/main/packages/button#test-harnesses)
- Exports the constant, `LGIDS_BUTTON`, which stores `data-lgid` values.



8 changes: 8 additions & 0 deletions .changeset/sour-crabs-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@leafygreen-ui/checkbox': minor
---

- Exports `getTestUtils`, a util to reliably interact with `LG Checkbox` in a product test suite. For more details, check out the [README](https://github.com/mongodb/leafygreen-ui/tree/main/packages/checkbox#test-harnesses)
- Exports the constant, `LGIDS_CHECKBOX`, which stores `data-lgid` values.
- Leverages the `'aria-label'` prop when passed

70 changes: 70 additions & 0 deletions packages/button/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,73 @@ npm install @leafygreen-ui/button
| ... | native attributes of component passed to as prop | Any other properties will be spread on the root element | |

_Note: In order to make this Component act as a submit button, the recommended approach is to pass `submit` as the `type` prop. Note it is also valid to pass `input` to the `as` prop, and the button's content's to the `value` prop -- in this case, do not supply children to the component._

# Test Harnesses

## getTestUtils()

`getTestUtils()` is a util that allows consumers to reliably interact with `LG Button` in a product test suite. If the `Button` component cannot be found, an error will be thrown.

### Usage

```tsx
import Button, { getTestUtils } from '@leafygreen-ui/button';

const utils = getTestUtils(lgId?: string); // lgId refers to the custom `data-lgid` attribute passed to `Button`. It defaults to 'lg-button' if left empty.
```

#### Single `Button`

```tsx
import { render } from '@testing-library/react';
import Button, { getTestUtils } from '@leafygreen-ui/button';

...

test('button', () => {
render(<Button>Click me</Button>);
const { getButton } = getTestUtils();

expect(getButton()).toBeInTheDocument();
});
```

#### Multiple `Button` components

When testing multiple `Button` components it is recommended to add the custom `data-lgid` attribute to each `Button`.

```tsx
import { render } from '@testing-library/react';
import Button, { getTestUtils } from '@leafygreen-ui/button';

...

test('button', () => {
render(
<>
<Button data-lgid="button-1">Click 1</Button>
<Button data-lgid="button-2" disabled>Click 2</Button>
</>,
);
const utilsOne = getTestUtils('button-1'); // data-lgid
const utilsTwo = getTestUtils('button-2'); // data-lgid
// First Button
expect(utilsOne.getButton()).toBeInTheDocument();
expect(utilsOne.isDisabled()).toBe(false);

// Second Button
expect(utilsTwo.getButton()).toBeInTheDocument();
expect(utilsTwo.isDisabled()).toBe(true);
});
```

### Test Utils

```tsx
const { getButton, isDisabled } = getTestUtils();
```

| Util | Description | Returns |
| ------------ | ------------------------------------- | ------------------- |
| `getButton` | Returns the input node | `HTMLButtonElement` |
| `isDisabled` | Returns whether the input is disabled | `boolean` |
5 changes: 3 additions & 2 deletions packages/button/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
"dependencies": {
"@leafygreen-ui/box": "^3.1.9",
"@leafygreen-ui/emotion": "^4.0.8",
"@leafygreen-ui/lib": "^13.3.0",
"@leafygreen-ui/palette": "^4.0.9",
"@leafygreen-ui/lib": "^13.4.0",
"@leafygreen-ui/palette": "^4.0.10",
"@leafygreen-ui/ripple": "^1.1.13",
"@leafygreen-ui/tokens": "^2.5.2",
"@lg-tools/test-harnesses": "^0.1.2",
"polished": "^4.2.2"
},
"devDependencies": {
Expand Down
14 changes: 8 additions & 6 deletions packages/button/src/Button/Button.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { BoxProps } from '@leafygreen-ui/box';
import { Spinner } from '@leafygreen-ui/loading-indicator';

import { ButtonProps } from '../types';
import { getTestUtils } from '../utils/getTestUtils';
import Button from '..';

const className = 'test-button-class';
Expand All @@ -16,8 +17,9 @@ const child = 'Button child';

function renderButton(props: BoxProps<'button', ButtonProps> = {}) {
const utils = render(<Button {...props} data-testid="button-id" />);
const button = utils.getByTestId('button-id');
return { ...utils, button };
const { getButton, isDisabled } = getTestUtils();
const button = getButton();
return { ...utils, button, isDisabled };
}

describe('packages/button', () => {
Expand Down Expand Up @@ -91,10 +93,10 @@ describe('packages/button', () => {
});

test(`renders with aria-disabled attribute but not disabled attribute when disabled prop is set`, () => {
const { button } = renderButton({
const { button, isDisabled } = renderButton({
disabled: true,
});
expect(button.getAttribute('aria-disabled')).toBeTruthy();
expect(isDisabled()).toBeTruthy();
expect(button.getAttribute('disabled')).toBeFalsy();
});

Expand Down Expand Up @@ -180,12 +182,12 @@ describe('packages/button', () => {
});

test(`does not render the disabled attribute for a disabled link`, () => {
const { button } = renderButton({
const { button, isDisabled } = renderButton({
href: 'http://mongodb.design',
disabled: true,
});
expect(button).not.toHaveAttribute('disabled');
expect(button).toHaveAttribute('aria-disabled', 'true');
expect(isDisabled()).toBe(true);
});

test('renders additional attributes not explicitly defined in props', () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/button/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
import { BaseFontSize } from '@leafygreen-ui/tokens';

import { ButtonContent } from '../ButtonContent/ButtonContent';
import { LGIDS_BUTTON } from '../constants';
import { ButtonClassName } from '../styles';
import { ButtonProps, Size, Variant } from '../types';

Expand All @@ -20,6 +21,7 @@ export const Button = React.forwardRef(function Button(
variant = Variant.Default,
size = Size.Default,
darkMode: darkModeProp,
'data-lgid': dataLgId = LGIDS_BUTTON.root,
baseFontSize = BaseFontSize.Body1,
disabled = false,
onClick,
Expand Down Expand Up @@ -50,6 +52,7 @@ export const Button = React.forwardRef(function Button(
});

const buttonProps = {
'data-lgid': dataLgId,
type: isAnchor ? undefined : type || 'button',
className: cx(ButtonClassName, buttonStyles, className),
ref: forwardRef,
Expand Down
5 changes: 5 additions & 0 deletions packages/button/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const LGID_ROOT = 'lg-button';

export const LGIDS_BUTTON = {
root: LGID_ROOT,
} as const;
3 changes: 2 additions & 1 deletion packages/button/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { HTMLProps } from 'react';

import { LgIdProps } from '@leafygreen-ui/lib';
import { BaseFontSize } from '@leafygreen-ui/tokens';

export const Variant = {
Expand Down Expand Up @@ -35,7 +36,7 @@ export const FontSize = {

export type FontSize = (typeof FontSize)[keyof typeof FontSize];

export interface ButtonProps {
export interface ButtonProps extends LgIdProps {
// Would prefer to use Pick<> to extract these properties, but they would not be correctly imported into Storybook otherwise.
// https://github.com/storybookjs/storybook/issues/14798

Expand Down
110 changes: 110 additions & 0 deletions packages/button/src/utils/getTestUtils.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React from 'react';
import { renderAsyncTest } from '@lg-tools/test-harnesses';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import Button from '..';

import { getTestUtils } from './getTestUtils';

const renderButtonAsync = () =>
renderAsyncTest(<Button>Click me</Button>, render);

function renderButton(props = {}) {
render(<Button {...props}>Click me</Button>);
}

function renderMultipleToggles() {
render(
<>
<Button data-lgid="lg-Button-1">Click me</Button>
<Button data-lgid="lg-Button-2" disabled>
Click me{' '}
</Button>
</>,
);
}

describe('packages/button/getTestUtils', () => {
describe('renders properly', () => {
test('throws error if LG Button is not found', () => {
render(<Button>Click me</Button>);

try {
const _utils = getTestUtils();
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error).toHaveProperty(
'message',
expect.stringMatching(
/Unable to find an element by: \[data-lgid="lg-button"\]/,
),
);
}
});
});

describe('single button', () => {
test('getButton', () => {
renderButton();
const { getButton } = getTestUtils();

expect(getButton()).toBeInTheDocument();
});

describe('isDisabled', () => {
test('to be false', () => {
renderButton();
const { isDisabled } = getTestUtils();

expect(isDisabled()).toBe(false);
});

test('to be true', () => {
renderButton({ disabled: true });
const { isDisabled } = getTestUtils();

expect(isDisabled()).toBe(true);
});
});
});

describe('multiple toggles', () => {
test('getButton', () => {
renderMultipleToggles();
const utilsOne = getTestUtils('lg-Button-1');
const utilsTwo = getTestUtils('lg-Button-2');

expect(utilsOne.getButton()).toBeInTheDocument();
expect(utilsTwo.getButton()).toBeInTheDocument();
});
});

describe('async component', () => {
test('find LG Button after awaiting an async component', async () => {
const { openButton, findByTestId, asyncTestComponentId } =
renderButtonAsync();

userEvent.click(openButton);

const asyncComponent = await findByTestId(asyncTestComponentId);
expect(asyncComponent).toBeInTheDocument();

// After awaiting asyncComponent, look for button
const { getButton } = getTestUtils();
expect(getButton()).toBeInTheDocument();
});

test('find LG Button after awaiting getTestUtils', async () => {
const { openButton } = renderButtonAsync();

userEvent.click(openButton);

// awaiting getTestUtils
await waitFor(() => {
const { getButton } = getTestUtils();
expect(getButton()).toBeInTheDocument();
});
});
});
});
27 changes: 27 additions & 0 deletions packages/button/src/utils/getTestUtils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getByLgId } from '@lg-tools/test-harnesses';

import { LGIDS_BUTTON } from '../constants';

import { GetTestUtilsReturnType } from './getTestUtils.types';

export const getTestUtils = <T extends HTMLElement = HTMLElement>(
lgId: string = LGIDS_BUTTON.root,
): GetTestUtilsReturnType<T> => {
/**
* Queries the DOM for the element using the `data-lgid` data attribute.
* Will throw if no element is found.
*/
const element: T = getByLgId!(lgId);

/**
* Returns the disabled attribute on the input.
*/
const isButtonDisabled = () => {
return element.getAttribute('aria-disabled') === 'true';
};

return {
getButton: () => element,
isDisabled: () => isButtonDisabled(),
};
};
6 changes: 6 additions & 0 deletions packages/button/src/utils/getTestUtils.types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FormUtils } from '@lg-tools/test-harnesses';

export interface GetTestUtilsReturnType<T extends HTMLElement> {
getButton: () => T;
isDisabled: FormUtils['isDisabled'];
}
1 change: 1 addition & 0 deletions packages/button/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getTestUtils } from './getTestUtils';
Loading

0 comments on commit 1ec45a7

Please sign in to comment.