Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Expand Up @@ -6,4 +6,4 @@

> `const` **default**: `FC`\<[`IItemModalProps`](../../../../../types/shared-components/ActionItems/interface/interfaces/IItemModalProps.md)\>

Defined in: [src/screens/OrganizationActionItems/ActionItemModal/ActionItemModal.tsx:67](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/OrganizationActionItems/ActionItemModal/ActionItemModal.tsx#L67)
Defined in: [src/screens/OrganizationActionItems/ActionItemModal/ActionItemModal.tsx:62](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/OrganizationActionItems/ActionItemModal/ActionItemModal.tsx#L62)
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
14 changes: 9 additions & 5 deletions src/components/AdminPortal/ApplyToSelector/ApplyToSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useId } from 'react';
import { Form } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
import type {
Expand All @@ -19,6 +19,10 @@ const ApplyToSelector: React.FC<InterfaceApplyToSelectorProps> = ({
applyTo,
onChange,
}) => {
const uid = useId();
const name = `applyTo-${uid}`;
const seriesId = `${name}-series`; // i18n-ignore-line
const instanceId = `${name}-instance`; // i18n-ignore-line
const { t } = useTranslation('translation', {
keyPrefix: 'organizationActionItems',
});
Expand All @@ -29,16 +33,16 @@ const ApplyToSelector: React.FC<InterfaceApplyToSelectorProps> = ({
<Form.Check
type="radio"
label={t('entireSeries')}
name="applyTo"
id="applyToSeries"
name={name}
id={seriesId}
checked={applyTo === 'series'}
onChange={() => onChange('series')}
/>
<Form.Check
type="radio"
label={t('thisEventOnly')}
name="applyTo"
id="applyToInstance"
name={name}
id={instanceId}
checked={applyTo === 'instance'}
onChange={() => onChange('instance')}
/>
Expand Down
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();
});
Comment on lines +72 to +118
Copy link
Contributor

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:

it('calls onTypeChange with volunteer when Enter key is pressed on volunteer chip', 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) {
    volunteerChip.focus();
    await user.keyboard('{Enter}');
  }

  expect(onTypeChange).toHaveBeenCalledWith('volunteer');
});
🤖 Prompt for AI Agents
In
@src/components/AdminPortal/AssignmentTypeSelector/AssignmentTypeSelector.spec.tsx
around lines 72 - 118, Add explicit keyboard-interaction tests for the
interactive chips: create separate test cases (e.g., it('calls onTypeChange with
volunteer when Enter key is pressed on volunteer chip') and corresponding tests
for Space and for the volunteerGroup chip) that render via renderComponent,
query the chip using screen.getByText('Volunteer').closest('[role="button"]') or
'Volunteer Group', call .focus() on the returned
volunteerChip/volunteerGroupChip, then simulate keyboard activation with
userEvent.setup() followed by await user.keyboard('{Enter}') and await
user.keyboard('{Space}') as separate tests, and assert onTypeChange was called
with the correct value ('volunteer' or 'volunteerGroup') and that
onClearVolunteer/onClearVolunteerGroup were invoked where appropriate.


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
Copy link
Contributor

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 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 structure
it('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
});

Loading
Loading