Browse Source

Update tests

Add tests for choice elements.
master
TheoryOfNekomata 1 year ago
parent
commit
320a2e8eac
11 changed files with 274 additions and 27 deletions
  1. +1
    -0
      TODO.md
  2. +4
    -1
      categories/action/react/.eslintrc
  3. +1
    -0
      categories/action/react/package.json
  4. +0
    -4
      categories/action/react/setupTests.ts
  5. +8
    -9
      categories/action/react/src/components/ActionButton/ActionButton.test.tsx
  6. +3
    -1
      categories/choice/react/package.json
  7. +1
    -7
      categories/choice/react/pridepack.json
  8. +3
    -1
      categories/choice/react/src/components/ComboBox/index.tsx
  9. +235
    -0
      categories/choice/react/src/components/DropdownSelect/DropdownSelect.test.tsx
  10. +6
    -1
      categories/choice/react/src/components/DropdownSelect/index.tsx
  11. +12
    -3
      pnpm-lock.yaml

+ 1
- 0
TODO.md View File

@@ -66,3 +66,4 @@

# Others
- [X] Add `select-none` to input labels, etc.
- [ ] Test all components!

+ 4
- 1
categories/action/react/.eslintrc View File

@@ -3,7 +3,10 @@
"rules": {
"quote-props": "off",
"react/jsx-props-no-spreading": "off",
"react/button-has-type": "off"
"react/button-has-type": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"import/no-extraneous-dependencies": "off"
},
"extends": [
"lxsmnsyc/typescript/react"


+ 1
- 0
categories/action/react/package.json View File

@@ -18,6 +18,7 @@
"@testing-library/user-event": "^14.4.3",
"@types/node": "^18.14.1",
"@types/react": "^18.0.27",
"@types/testing-library__jest-dom": "^5.14.7",
"eslint": "^8.35.0",
"eslint-config-lxsmnsyc": "^0.5.0",
"jsdom": "^21.1.0",


+ 0
- 4
categories/action/react/setupTests.ts View File

@@ -1,4 +0,0 @@
import matchers from '@testing-library/jest-dom/matchers';
import { expect } from 'vitest';

expect.extend(matchers);

+ 8
- 9
categories/action/react/src/components/ActionButton/ActionButton.test.tsx View File

@@ -12,13 +12,12 @@ import {
it,
expect, afterEach,
} from 'vitest';
import matchers from '@testing-library/jest-dom/matchers';
import {
ActionButton,
} from '.';
import matchers from '@testing-library/jest-dom/matchers';
expect.extend(matchers);

vi.mock('@tesseract-design/web-base-button');
expect.extend(matchers);

describe('ActionButton', () => {
afterEach(() => {
@@ -65,7 +64,7 @@ describe('ActionButton', () => {
});

it('handles click events', async () => {
const onClick = vi.fn().mockImplementationOnce((e) => { e.preventDefault() });
const onClick = vi.fn().mockImplementationOnce((e) => { e.preventDefault(); });
render(
<ActionButton
onClick={onClick}
@@ -94,7 +93,7 @@ describe('ActionButton', () => {
${'small'} | ${'h-10'}
${'medium'} | ${'h-12'}
${'large'} | ${'h-16'}
`('on %s size', ({
`('on $size size', ({
size,
className,
}: { size: Button.Size, className: string }) => {
@@ -127,7 +126,7 @@ describe('ActionButton', () => {
${'bare'} | ${'bg-negative'}
${'outline'} | ${'border-2'}
${'filled'} | ${'bg-primary'}
`('renders a button with variant %s', ({
`('renders a button with $variant variant', ({
variant,
className,
}: { variant: Button.Variant, className: string }) => {
@@ -157,7 +156,7 @@ describe('ActionButton', () => {
render(
<ActionButton>
Foo
</ActionButton>
</ActionButton>,
);

const children: HTMLElement = screen.getByTestId('children');
@@ -168,7 +167,7 @@ describe('ActionButton', () => {
render(
<ActionButton
type={buttonType}
/>
/>,
);
const button: HTMLButtonElement = screen.getByRole('button');
expect(button).toHaveProperty('type', buttonType);
@@ -178,7 +177,7 @@ describe('ActionButton', () => {
render(
<ActionButton
disabled
/>
/>,
);
const button: HTMLButtonElement = screen.getByTestId('button');
expect(button).toBeDisabled();


+ 3
- 1
categories/choice/react/package.json View File

@@ -15,8 +15,10 @@
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "^18.14.1",
"@types/react": "^18.0.27",
"@types/testing-library__jest-dom": "^5.14.7",
"eslint": "^8.35.0",
"eslint-config-lxsmnsyc": "^0.5.0",
"jsdom": "^21.1.0",
@@ -83,4 +85,4 @@
"typesVersions": {
"*": {}
}
}
}

+ 1
- 7
categories/choice/react/pridepack.json View File

@@ -1,9 +1,3 @@
{
"target": "es2018",
"entryPoints": {
".": "src/index.ts",
"./dist/DropdownSelect.css": "src/components/DropdownSelect/DropdownSelect.css",
"./dist/RadioButton.css": "src/components/RadioButton/RadioButton.css",
"./dist/RadioTickBox.css": "src/components/RadioTickBox/RadioTickBox.css"
}
"target": "es2018"
}

+ 3
- 1
categories/choice/react/src/components/ComboBox/index.tsx View File

@@ -10,7 +10,7 @@ export type ComboBoxDerivedElement = HTMLInputElement;
/**
* Props of the {@link ComboBox} component.
*/
export interface ComboBoxProps extends Omit<React.HTMLProps<ComboBoxDerivedElement>, 'size' | 'type' | 'style' | 'label' | 'list' | 'inputMode'> {
export interface ComboBoxProps extends Omit<React.HTMLProps<ComboBoxDerivedElement>, 'size' | 'type' | 'label' | 'list' | 'inputMode'> {
/**
* Short textual description indicating the nature of the component's value.
*/
@@ -73,6 +73,7 @@ export const ComboBox = React.forwardRef<ComboBoxDerivedElement, ComboBoxProps>(
children,
inputMode = 'text' as const,
id: idProp,
style,
...etcProps
}: ComboBoxProps,
forwardedRef,
@@ -106,6 +107,7 @@ export const ComboBox = React.forwardRef<ComboBoxDerivedElement, ComboBoxProps>(
},
className,
)}
style={style}
>
<input
{...etcProps}


+ 235
- 0
categories/choice/react/src/components/DropdownSelect/DropdownSelect.test.tsx View File

@@ -0,0 +1,235 @@
import * as React from 'react';
import {
cleanup,
render,
screen,
} from '@testing-library/react';
import { TextControl } from '@tesseract-design/web-base';
import userEvent from '@testing-library/user-event';
import {
afterEach,
expect,
vi,
describe,
it,
} from 'vitest';
import matchers from '@testing-library/jest-dom/matchers';
import {
DropdownSelect,
} from '.';

expect.extend(matchers);

describe('DropdownSelect', () => {
afterEach(() => {
cleanup();
});

it('renders a combobox', () => {
render(<DropdownSelect />);
const combobox = screen.getByRole('combobox');
expect(combobox).toBeInTheDocument();
});

it('renders a border', () => {
render(
<DropdownSelect
border
/>,
);
const border = screen.getByTestId('border');
expect(border).toBeInTheDocument();
});

it('renders a label', () => {
render(
<DropdownSelect
label="foo"
/>,
);
const combobox = screen.getByLabelText('foo');
expect(combobox).toBeInTheDocument();
const label = screen.getByTestId('label');
expect(label).toHaveTextContent('foo');
});

it('renders a hidden label', () => {
render(
<DropdownSelect
label="foo"
hiddenLabel
/>,
);
const combobox = screen.getByLabelText('foo');
expect(combobox).toBeInTheDocument();
const label = screen.getByTestId('label');
expect(label).toHaveClass('sr-only');
});

it('renders a hint', () => {
render(
<DropdownSelect
hint="foo"
/>,
);
const hint = screen.getByTestId('hint');
expect(hint).toBeInTheDocument();
});

it('render options with implicit values', () => {
render(
<DropdownSelect>
<option>foo</option>
<option>bar</option>
</DropdownSelect>,
);
const combobox = screen.getByRole('combobox');
expect(combobox.children).toHaveLength(2);
});

it('renders valid options', () => {
render(
<DropdownSelect>
<option value="foo">foo</option>
<option value="bar">bar</option>
</DropdownSelect>,
);
const combobox = screen.getByRole('combobox');
expect(combobox.children).toHaveLength(2);
});

it('renders option groups', () => {
render(
<DropdownSelect>
<optgroup label="foo">
<option value="baz">baz</option>
</optgroup>
<optgroup label="bar">
<option value="quux">quux</option>
<option value="quuux">quuux</option>
</optgroup>
</DropdownSelect>,
);
const combobox = screen.getByRole('combobox');
expect(combobox.children).toHaveLength(2);
expect(combobox.children[0].children).toHaveLength(1);
expect(combobox.children[1].children).toHaveLength(2);
});

describe.each`
size | inputClassNames | hintClassNames | indicatorClassNames
${'small'} | ${['h-10']} | ${['pr-10']} | ${['w-10']}
${'medium'} | ${['h-12']} | ${['pr-12']} | ${['w-12']}
${'large'} | ${['h-16']} | ${['pr-16']} | ${['w-16']}
`('on $size size', ({
size,
inputClassNames,
hintClassNames,
indicatorClassNames,
}: {
size: TextControl.Size,
inputClassNames: string[],
hintClassNames: string[],
indicatorClassNames: string[],
}) => {
it('renders input styles', () => {
render(
<DropdownSelect
size={size}
/>,
);

const combobox = screen.getByRole('combobox');
expect(combobox).toHaveClass(...inputClassNames);
});

it('renders hint styles', () => {
render(
<DropdownSelect
size={size}
hint="hint"
indicator="a"
/>,
);

const hint = screen.getByTestId('hint');
expect(hint).toHaveClass(...hintClassNames);
});

it('renders indicator styles', () => {
render(
<DropdownSelect
size={size}
indicator="a'"
/>,
);

const indicator = screen.getByTestId('indicator');
expect(indicator).toHaveClass(...indicatorClassNames);
});
});

it('renders a block input', () => {
render(
<DropdownSelect
block
/>,
);

const base = screen.getByTestId('base');
expect(base).toHaveClass('block');
});

describe.each`
variant | inputClassNames | hintClassNames
${'default'} | ${['pl-4']} | ${['bottom-0', 'pl-4', 'pb-1']}
${'alternate'} | ${['pl-1.5', 'pt-4']} | ${['top-0.5']}
`('on $variant variant', ({
variant,
inputClassNames,
hintClassNames,
}: {
variant: TextControl.Variant,
inputClassNames: string[],
hintClassNames: string[],
}) => {
it('renders input styles', () => {
render(
<DropdownSelect
variant={variant}
/>,
);

const combobox = screen.getByRole('combobox');
expect(combobox).toHaveClass(...inputClassNames);
});

it('renders hint styles', () => {
render(
<DropdownSelect
variant={variant}
hint="hint"
/>,
);

const hint = screen.getByTestId('hint');
expect(hint).toHaveClass(...hintClassNames);
});
});

it('handles change events', async () => {
const onChange = vi.fn().mockImplementationOnce((e) => { e.preventDefault(); })
render(
<DropdownSelect
onChange={onChange}
>
<option value="foo">foo</option>
<option value="bar">bar</option>
</DropdownSelect>,
);
const combobox: HTMLSelectElement = screen.getByRole('combobox');
const [, secondOption] = screen.getAllByRole('option');
await userEvent.selectOptions(combobox, secondOption);
expect(onChange).toBeCalled();
});
});

+ 6
- 1
categories/choice/react/src/components/DropdownSelect/index.tsx View File

@@ -10,7 +10,7 @@ export type DropdownSelectDerivedElement = HTMLSelectElement;
/**
* Props of the {@link DropdownSelect} component.
*/
export interface DropdownSelectProps extends Omit<React.HTMLProps<DropdownSelectDerivedElement>, 'size' | 'type' | 'style' | 'label' | 'list' | 'multiple'> {
export interface DropdownSelectProps extends Omit<React.HTMLProps<DropdownSelectDerivedElement>, 'size' | 'type' | 'label' | 'list' | 'multiple'> {
/**
* Short textual description indicating the nature of the component's value.
*/
@@ -61,6 +61,7 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro
className,
children,
id: idProp,
style,
...etcProps
}: DropdownSelectProps,
forwardedRef,
@@ -80,6 +81,8 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro
},
className,
)}
data-testid="base"
style={style}
>
<select
{...etcProps}
@@ -87,6 +90,7 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro
id={id}
aria-labelledby={labelId}
data-testid="input"
role="combobox"
className={clsx(
'tesseract-design-dropdown-select bg-negative rounded-inherit w-full peer block appearance-none cursor-pointer select-none font-inherit',
'focus:outline-0',
@@ -180,6 +184,7 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro
)}
{indicator && (
<div
data-testid="indicator"
className={clsx(
'text-center flex items-center justify-center peer-disabled:opacity-50 aspect-square absolute bottom-0 right-0 pointer-events-none select-none',
{


+ 12
- 3
pnpm-lock.yaml View File

@@ -54,6 +54,9 @@ importers:
'@types/react':
specifier: ^18.0.27
version: 18.2.14
'@types/testing-library__jest-dom':
specifier: ^5.14.7
version: 5.14.7
eslint:
specifier: ^8.35.0
version: 8.43.0
@@ -152,12 +155,18 @@ importers:
'@testing-library/react':
specifier: ^13.4.0
version: 13.4.0(react-dom@18.2.0)(react@18.2.0)
'@testing-library/user-event':
specifier: ^14.4.3
version: 14.4.3(@testing-library/dom@8.20.1)
'@types/node':
specifier: ^18.14.1
version: 18.14.1
'@types/react':
specifier: ^18.0.27
version: 18.2.14
'@types/testing-library__jest-dom':
specifier: ^5.14.7
version: 5.14.7
eslint:
specifier: ^8.35.0
version: 8.43.0
@@ -1906,7 +1915,7 @@ packages:
dependencies:
'@adobe/css-tools': 4.2.0
'@babel/runtime': 7.22.5
'@types/testing-library__jest-dom': 5.14.6
'@types/testing-library__jest-dom': 5.14.7
aria-query: 5.3.0
chalk: 3.0.0
css.escape: 1.5.1
@@ -2054,8 +2063,8 @@ packages:
resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
dev: true

/@types/testing-library__jest-dom@5.14.6:
resolution: {integrity: sha512-FkHXCb+ikSoUP4Y4rOslzTdX5sqYwMxfefKh1GmZ8ce1GOkEHntSp6b5cGadmNfp5e4BMEWOMx+WSKd5/MqlDA==}
/@types/testing-library__jest-dom@5.14.7:
resolution: {integrity: sha512-PFDoAbR9y8pD9+41oM1Yy0nVCkaRPlklmDZoPCXhNpR0ZO13HAYWqdNEjLtvIiveBmfB/+jdvmuOVeOXehKOaA==}
dependencies:
'@types/jest': 29.5.2
dev: true


Loading…
Cancel
Save