Skip to content

Commit

Permalink
test(atomic): test radio-button render function (#4896)
Browse files Browse the repository at this point in the history
* Add specs for radio-button render function
* Remove tsconfig dependencies from stencil tsconfig.
* Add
[`@testing-library/jest-dom`](https://www.npmjs.com/package/@testing-library/jest-dom?activeTab=dependencies)
to extend Jest’s matchers with additional utilities for testing DOM
elements, such as `toBeInTheDocument`, etc.

https://coveord.atlassian.net/browse/KIT-3898
  • Loading branch information
y-lakhdar authored Jan 30, 2025
1 parent 7b277e1 commit 7c5ac43
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/atomic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"@storybook/test": "8.1.11",
"@storybook/web-components": "8.1.11",
"@storybook/web-components-vite": "8.1.11",
"@testing-library/jest-dom": "6.6.3",
"@types/core-js": "2.5.8",
"@types/escape-html": "1.0.4",
"@types/jest": "29.5.12",
Expand Down
4 changes: 2 additions & 2 deletions packages/atomic/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"executor": "nx:run-commands",
"options": {
"commands": [
"node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build",
"node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build --tsConfig tsconfig.stencil.json",
"node ./scripts/stencil-proxy.mjs",
"node ./scripts/build.mjs --config=tsconfig.lit.json",
"node ./scripts/process-css.mjs --config=tsconfig.lit.json ",
Expand Down Expand Up @@ -114,7 +114,7 @@
"dependsOn": ["^build", "build:locales"],
"executor": "nx:run-commands",
"options": {
"command": "node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build --dev --watch --serve",
"command": "node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build --tsConfig tsconfig.stencil.json --dev --watch --serve",
"cwd": "{projectRoot}"
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/atomic/scripts/watch.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async function rebuild(event, fileName) {
return;
}
const commands = [
'node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build',
'node --max_old_space_size=6144 ../../node_modules/@stencil/core/bin/stencil build --tsConfig tsconfig.stencil.json',
'node ./scripts/stencil-proxy.mjs',
'node ./scripts/build.mjs --config=tsconfig.lit.json',
'node ./scripts/process-css.mjs --config=tsconfig.lit.json ',
Expand Down
149 changes: 149 additions & 0 deletions packages/atomic/src/components/common/radio-button.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import {fireEvent, within} from '@storybook/test';
import {html, render} from 'lit';
import {vi} from 'vitest';
import {createRipple} from '../../utils/ripple';
import {radioButton, RadioButtonProps} from './radio-button';

vi.mock('../../utils/ripple', () => ({
createRipple: vi.fn(),
}));

describe('radioButton', () => {
let container: HTMLElement;

beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});

afterEach(() => {
document.body.removeChild(container);
});

const renderRadioButton = (
props: Partial<RadioButtonProps>
): HTMLInputElement => {
render(
html`${radioButton({...props, groupName: 'test-group'})}`,
container
);
return within(container).getByRole('radio');
};

it('should render a radio button with the correct attributes', () => {
const props = {
text: 'Test Radio Button',
checked: true,
ariaLabel: 'Test Radio Button',
};

const input = renderRadioButton(props);

expect(input).toBeInTheDocument();
expect(input.name).toBe('test-group');
expect(input.checked).toBe(true);
expect(input.getAttribute('aria-label')).toBe('Test Radio Button');
expect(input.value).toBe('Test Radio Button');
expect(input.classList.contains('selected')).toBe(true);
});

it('should call onChecked when the radio button is checked', async () => {
const onChecked = vi.fn();
const props = {
onChecked,
};

const input = renderRadioButton(props);
await fireEvent.click(input);

await expect(onChecked).toHaveBeenCalled();
});

it('should handle keyboard navigation', async () => {
const {focus, keyDown} = fireEvent;
const getRadio = (index: number) =>
within(container).getByLabelText(`radio-${index}`);
const props = {
groupName: 'test-group',
selectWhenFocused: false,
};

render(
html`${radioButton({...props, text: 'radio-1'})}
${radioButton({...props, text: 'radio-2'})}
${radioButton({...props, text: 'radio-3'})}`,
container
);

const inputs = within(container).getAllByRole('radio');

await focus(inputs[0]);
await keyDown(inputs[0], {key: 'ArrowRight'});

await expect(getRadio(1)).toBeInTheDocument();

keyDown(inputs[1], {key: 'ArrowRight'});
await expect(getRadio(2)).toBeInTheDocument();

keyDown(inputs[2], {key: 'ArrowRight'});
await expect(getRadio(3)).toBeInTheDocument();
});

it('should create a ripple effect on mousedown', async () => {
const mockedRipple = vi.mocked(createRipple);
const props: Partial<RadioButtonProps> = {
style: 'primary',
};

const input = renderRadioButton(props);
await fireEvent.mouseDown(input);

await expect(mockedRipple).toHaveBeenCalledWith(expect.anything(), {
color: 'primary',
});
});

it('should render a radio button with the correct class', async () => {
const props = {
class: 'test-class',
};

const input = renderRadioButton(props);
expect(input).toBeInTheDocument();
expect(input.classList.contains('test-class')).toBe(true);
expect(input.classList.contains('btn-radio')).toBe(true);
expect(input.classList.contains('selected')).toBe(false);
});

it('should render a radio button with the correct part attribute', () => {
const props = {
part: 'test-part',
};

const input = renderRadioButton(props);
expect(input.getAttribute('part')).toBe('test-part');
});

it('should render a radio button with the correct ref', () => {
const ref = vi.fn();
const props = {
groupName: 'test-group',
ref,
};

render(html`${radioButton(props)}`, container);

expect(ref).toHaveBeenCalled();
});

it('should render a radio button with the correct aria-current attribute', () => {
const props: Partial<RadioButtonProps> = {
ariaCurrent: 'page',
};

renderRadioButton(props);
expect(
within(container).getByRole('radio', {current: 'page'})
).toBeInTheDocument();
});
});
1 change: 0 additions & 1 deletion packages/atomic/src/components/common/radio-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export interface RadioButtonProps {
ref?: RefOrCallback;
}

// TODO: KIT-3822: add unit tests to this function
export const radioButton = (props: RadioButtonProps): TemplateResult => {
const classNames = {
'btn-radio': true,
Expand Down
19 changes: 17 additions & 2 deletions packages/atomic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
{
"extends": "./tsconfig.stencil.json",
"extends": "../../tsconfig.json",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": false,
"experimentalDecorators": true,
"lib": ["dom", "ES2023"],
"moduleResolution": "Bundler",
"module": "ES2022",
"target": "ES2021",
"resolveJsonModule": true,
"useDefineForClassFields": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"jsx": "react",
"jsxFactory": "h",
"types": ["@testing-library/jest-dom"],
"plugins": [
{
"name": "ts-lit-plugin",
Expand All @@ -15,5 +29,6 @@
}
]
},
"exclude": ["node_modules", "src/external-builds"]
"exclude": ["node_modules", "src/external-builds"],
"include": ["src"]
}
1 change: 1 addition & 0 deletions packages/atomic/tsconfig.stencil.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"src/external-builds",
"**/*.stories.tsx",
"**/*.stories.ts",
"**/*.spec.ts",
"**/*.stories.js",
"**/e2e/**/*"
]
Expand Down

0 comments on commit 7c5ac43

Please sign in to comment.