-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
refactor(ActionItemModal): extract AssignmentTypeSelector component [Part 2/5] #6383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| [Admin Docs](/) | ||
|
|
||
| *** | ||
|
|
||
| # Variable: default | ||
|
|
||
| > `const` **default**: `React.FC`\<[`InterfaceAssignmentTypeSelectorProps`](../../../../../types/AdminPortal/AssignmentTypeSelector/interface/interfaces/InterfaceAssignmentTypeSelectorProps.md)\> | ||
|
|
||
| Defined in: [src/components/AdminPortal/AssignmentTypeSelector/AssignmentTypeSelector.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/AdminPortal/AssignmentTypeSelector/AssignmentTypeSelector.tsx#L14) | ||
|
|
||
| Chip-based toggle selector for choosing assignment type (volunteer or volunteer group). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| [Admin Docs](/) | ||
|
|
||
| *** | ||
|
|
||
| # Interface: InterfaceAssignmentTypeSelectorProps | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:11](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L11) | ||
|
|
||
| Props for AssignmentTypeSelector component. | ||
|
|
||
| ## Properties | ||
|
|
||
| ### assignmentType | ||
|
|
||
| > **assignmentType**: [`AssignmentType`](../type-aliases/AssignmentType.md) | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:13](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L13) | ||
|
|
||
| Current assignment type selection | ||
|
|
||
| *** | ||
|
|
||
| ### isVolunteerDisabled | ||
|
|
||
| > **isVolunteerDisabled**: `boolean` | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:17](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L17) | ||
|
|
||
| Whether volunteer chip is disabled | ||
|
|
||
| *** | ||
|
|
||
| ### isVolunteerGroupDisabled | ||
|
|
||
| > **isVolunteerGroupDisabled**: `boolean` | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L19) | ||
|
|
||
| Whether volunteer group chip is disabled | ||
|
|
||
| *** | ||
|
|
||
| ### onClearVolunteer() | ||
|
|
||
| > **onClearVolunteer**: () => `void` | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:21](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L21) | ||
|
|
||
| Callback to clear volunteer selection | ||
|
|
||
| #### Returns | ||
|
|
||
| `void` | ||
|
|
||
| *** | ||
|
|
||
| ### onClearVolunteerGroup() | ||
|
|
||
| > **onClearVolunteerGroup**: () => `void` | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:23](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L23) | ||
|
|
||
| Callback to clear volunteer group selection | ||
|
|
||
| #### Returns | ||
|
|
||
| `void` | ||
|
|
||
| *** | ||
|
|
||
| ### onTypeChange() | ||
|
|
||
| > **onTypeChange**: (`type`) => `void` | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L15) | ||
|
|
||
| Callback fired when assignment type changes | ||
|
|
||
| #### Parameters | ||
|
|
||
| ##### type | ||
|
|
||
| [`AssignmentType`](../type-aliases/AssignmentType.md) | ||
|
|
||
| #### Returns | ||
|
|
||
| `void` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [Admin Docs](/) | ||
|
|
||
| *** | ||
|
|
||
| # Type Alias: AssignmentType | ||
|
|
||
| > **AssignmentType** = `"volunteer"` \| `"volunteerGroup"` | ||
|
|
||
| Defined in: [src/types/AdminPortal/AssignmentTypeSelector/interface.ts:6](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/types/AdminPortal/AssignmentTypeSelector/interface.ts#L6) | ||
|
|
||
| Type representing the assignment target for action items. | ||
| - 'volunteer': Assign to individual volunteer | ||
| - 'volunteerGroup': Assign to volunteer group |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,185 @@ | ||
| import React from 'react'; | ||
| import { render, screen } from '@testing-library/react'; | ||
| import userEvent from '@testing-library/user-event'; | ||
| import { describe, it, expect, vi, afterEach } from 'vitest'; | ||
| import { I18nextProvider } from 'react-i18next'; | ||
| import i18n from 'utils/i18nForTest'; | ||
| import AssignmentTypeSelector from './AssignmentTypeSelector'; | ||
| import type { AssignmentType } from 'types/AdminPortal/AssignmentTypeSelector/interface'; | ||
|
|
||
| describe('AssignmentTypeSelector', () => { | ||
| afterEach(() => { | ||
| vi.clearAllMocks(); | ||
| }); | ||
|
|
||
| const renderComponent = ( | ||
| assignmentType: AssignmentType = 'volunteer', | ||
| onTypeChange = vi.fn(), | ||
| isVolunteerDisabled = false, | ||
| isVolunteerGroupDisabled = false, | ||
| onClearVolunteer = vi.fn(), | ||
| onClearVolunteerGroup = vi.fn(), | ||
| ) => { | ||
| return render( | ||
| <I18nextProvider i18n={i18n}> | ||
| <AssignmentTypeSelector | ||
| assignmentType={assignmentType} | ||
| onTypeChange={onTypeChange} | ||
| isVolunteerDisabled={isVolunteerDisabled} | ||
| isVolunteerGroupDisabled={isVolunteerGroupDisabled} | ||
| onClearVolunteer={onClearVolunteer} | ||
| onClearVolunteerGroup={onClearVolunteerGroup} | ||
| /> | ||
| </I18nextProvider>, | ||
| ); | ||
| }; | ||
|
|
||
| it('renders both chip options', () => { | ||
| renderComponent(); | ||
|
|
||
| expect(screen.getByText('Volunteer')).toBeInTheDocument(); | ||
| expect(screen.getByText('Volunteer Group')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('shows volunteer chip as selected when assignmentType is volunteer', () => { | ||
| renderComponent('volunteer'); | ||
|
|
||
| const volunteerChip = screen | ||
| .getByText('Volunteer') | ||
| .closest('[role="button"]'); | ||
| const volunteerGroupChip = screen | ||
| .getByText('Volunteer Group') | ||
| .closest('[role="button"]'); | ||
|
|
||
| expect(volunteerChip).toHaveAttribute('aria-disabled', 'false'); | ||
| expect(volunteerGroupChip).toHaveAttribute('aria-disabled', 'false'); | ||
| }); | ||
|
|
||
| it('shows volunteer group chip as selected when assignmentType is volunteerGroup', () => { | ||
| renderComponent('volunteerGroup'); | ||
|
|
||
| const volunteerChip = screen | ||
| .getByText('Volunteer') | ||
| .closest('[role="button"]'); | ||
| const volunteerGroupChip = screen | ||
| .getByText('Volunteer Group') | ||
| .closest('[role="button"]'); | ||
|
|
||
| expect(volunteerChip).toHaveAttribute('aria-disabled', 'false'); | ||
| expect(volunteerGroupChip).toHaveAttribute('aria-disabled', 'false'); | ||
| }); | ||
|
|
||
| it('calls onTypeChange with volunteer when volunteer chip is clicked', async () => { | ||
| const onTypeChange = vi.fn(); | ||
| const onClearVolunteerGroup = vi.fn(); | ||
| renderComponent( | ||
| 'volunteerGroup', | ||
| onTypeChange, | ||
| false, | ||
| false, | ||
| vi.fn(), | ||
| onClearVolunteerGroup, | ||
| ); | ||
|
|
||
| const user = userEvent.setup(); | ||
| const volunteerChip = screen | ||
| .getByText('Volunteer') | ||
| .closest('[role="button"]'); | ||
| if (volunteerChip) { | ||
| await user.click(volunteerChip); | ||
| } | ||
|
|
||
| expect(onTypeChange).toHaveBeenCalledWith('volunteer'); | ||
| expect(onClearVolunteerGroup).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('calls onTypeChange with volunteerGroup when volunteer group chip is clicked', async () => { | ||
| const onTypeChange = vi.fn(); | ||
| const onClearVolunteer = vi.fn(); | ||
| renderComponent( | ||
| 'volunteer', | ||
| onTypeChange, | ||
| false, | ||
| false, | ||
| onClearVolunteer, | ||
| vi.fn(), | ||
| ); | ||
|
|
||
| const user = userEvent.setup(); | ||
| const volunteerGroupChip = screen | ||
| .getByText('Volunteer Group') | ||
| .closest('[role="button"]'); | ||
| if (volunteerGroupChip) { | ||
| await user.click(volunteerGroupChip); | ||
| } | ||
|
|
||
| expect(onTypeChange).toHaveBeenCalledWith('volunteerGroup'); | ||
| expect(onClearVolunteer).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('does not call onTypeChange when disabled volunteer chip is clicked', async () => { | ||
| const onTypeChange = vi.fn(); | ||
| const onClearVolunteerGroup = vi.fn(); | ||
| renderComponent( | ||
| 'volunteerGroup', | ||
| onTypeChange, | ||
| true, | ||
| false, | ||
| vi.fn(), | ||
| onClearVolunteerGroup, | ||
| ); | ||
|
|
||
| const user = userEvent.setup(); | ||
| const volunteerChip = screen | ||
| .getByText('Volunteer') | ||
| .closest('[role="button"]'); | ||
| if (volunteerChip) { | ||
| await user.click(volunteerChip); | ||
| } | ||
|
|
||
| expect(onTypeChange).not.toHaveBeenCalled(); | ||
| expect(onClearVolunteerGroup).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('does not call onTypeChange when disabled volunteer group chip is clicked', async () => { | ||
| const onTypeChange = vi.fn(); | ||
| const onClearVolunteer = vi.fn(); | ||
| renderComponent( | ||
| 'volunteer', | ||
| onTypeChange, | ||
| false, | ||
| true, | ||
| onClearVolunteer, | ||
| vi.fn(), | ||
| ); | ||
|
|
||
| const user = userEvent.setup(); | ||
| const volunteerGroupChip = screen | ||
| .getByText('Volunteer Group') | ||
| .closest('[role="button"]'); | ||
| if (volunteerGroupChip) { | ||
| await user.click(volunteerGroupChip); | ||
| } | ||
|
|
||
| expect(onTypeChange).not.toHaveBeenCalled(); | ||
| expect(onClearVolunteer).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('renders with disabled state styling when volunteer chip is disabled', () => { | ||
| renderComponent('volunteerGroup', vi.fn(), true, false); | ||
|
|
||
| const volunteerChip = screen | ||
| .getByText('Volunteer') | ||
| .closest('div[aria-disabled="true"]'); | ||
| expect(volunteerChip).toHaveAttribute('aria-disabled', 'true'); | ||
| }); | ||
|
|
||
| it('renders with disabled state styling when volunteer group chip is disabled', () => { | ||
| renderComponent('volunteer', vi.fn(), false, true); | ||
|
|
||
| const volunteerGroupChip = screen | ||
| .getByText('Volunteer Group') | ||
| .closest('div[aria-disabled="true"]'); | ||
| expect(volunteerGroupChip).toHaveAttribute('aria-disabled', 'true'); | ||
| }); | ||
| }); | ||
|
Comment on lines
+168
to
+185
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Consider adding keyboard accessibility tests. While click interactions are well-tested, consider adding tests for keyboard navigation (Enter/Space key) on the chips to ensure accessibility compliance. Per repository learnings, prefer separate explicit test cases for each keyboard interaction. ♻️ Example keyboard test structureit('handles Enter key on volunteer chip when not disabled', async () => {
const onTypeChange = vi.fn();
renderComponent('volunteerGroup', onTypeChange, false, false);
const user = userEvent.setup();
const volunteerChip = screen.getByText('Volunteer').closest('[role="button"]');
if (volunteerChip) {
volunteerChip.focus();
await user.keyboard('{Enter}');
}
expect(onTypeChange).toHaveBeenCalledWith('volunteer');
});
it('handles Space key on volunteer chip when not disabled', async () => {
// Similar structure for Space key
}); |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider adding keyboard navigation tests.
Based on learnings, the project prefers separate explicit test cases for keyboard interactions (Enter key, Space key). Since these Chips are interactive elements, consider adding tests for keyboard activation:
🤖 Prompt for AI Agents