Skip to content

Commit

Permalink
Merge branch 'main' into modal-mousedown-onclick
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmenendez authored Jun 25, 2024
2 parents d2b3268 + b28d8be commit 51480ee
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 86 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/deploy-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
branch: 'release/update-carbon-deps'
commit-message: 'chore(release): update carbon deps'
Expand Down Expand Up @@ -82,7 +82,7 @@ jobs:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
branch: 'release/update-carbon-deps'
commit-message: 'chore(release): update carbon deps'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
branch: 'release/${{ github.event.inputs.tag }}'
commit-message: 'chore(release): ${{ github.event.inputs.tag }}'
Expand Down
4 changes: 3 additions & 1 deletion .whitesource
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"settingsInheritedFrom": "ibm-mend-config/mend-config@main",
"minSeverityLevel": "NONE"
"issueSettings": {
"minSeverityLevel": "NONE"
}
}
18 changes: 2 additions & 16 deletions e2e/components/DatePicker/DatePicker-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ test.describe('@avt DatePicker', () => {
},
});

// for some reason the firs tab is not working to focus the first tabstop, so focusing manually
// for some reason the first tab is not working to focus the first tabstop, so focusing manually
await page.getByRole('textbox', { name: 'Date Picker label' }).focus();
await expect(
page.getByRole('textbox', { name: 'Date Picker label' })
Expand All @@ -96,9 +96,6 @@ test.describe('@avt DatePicker', () => {
await page.keyboard.press('ArrowDown');
await expect(page.locator('span.today')).toBeFocused();
await page.keyboard.press('Escape');
await expect(
page.getByRole('textbox', { name: 'Date Picker label' })
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).not.toHaveClass(
/open/
);
Expand Down Expand Up @@ -126,18 +123,7 @@ test.describe('@avt DatePicker', () => {
await expect(page.locator('div.flatpickr-calendar')).toHaveClass(/open/);
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
await expect(
page.locator('input#date-picker-input-id-start')
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).not.toHaveClass(
/open/
);
await page.keyboard.press('Tab');
await expect(
page.locator('input#date-picker-input-id-finish')
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).toHaveClass(/open/);
await page.keyboard.press('Escape');
await page.keyboard.press('Enter');
await expect(
page.locator('input#date-picker-input-id-finish')
).toBeFocused();
Expand Down
13 changes: 0 additions & 13 deletions e2e/components/FluidDatePicker/FluidDatePicker-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ test.describe('@avt FluidDatePicker', () => {
await page.keyboard.press('ArrowDown');
await expect(page.locator('span.today')).toBeFocused();
await page.keyboard.press('Escape');
await expect(page.getByRole('textbox', { name: 'Label' })).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).not.toHaveClass(
/open/
);
Expand Down Expand Up @@ -98,18 +97,6 @@ test.describe('@avt FluidDatePicker', () => {
await expect(page.locator('div.flatpickr-calendar')).toHaveClass(/open/);
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
await expect(
page.locator('input#date-picker-input-id-start')
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).not.toHaveClass(
/open/
);
await page.keyboard.press('Tab');
await expect(
page.locator('input#date-picker-input-id-finish')
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).toHaveClass(/open/);
await page.keyboard.press('Escape');
await expect(
page.locator('input#date-picker-input-id-finish')
).toBeFocused();
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/icons/src/svg/32/kubernetes--worker-node.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 6 additions & 4 deletions packages/react/src/components/ComposedModal/ComposedModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import React, {
} from 'react';
import { isElement } from 'react-is';
import PropTypes from 'prop-types';
import { Layer } from '../Layer';
import { ModalHeader, type ModalHeaderProps } from './ModalHeader';
import { ModalFooter, type ModalFooterProps } from './ModalFooter';
import debounce from 'lodash.debounce';
Expand Down Expand Up @@ -97,13 +98,13 @@ export const ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(
: {};

return (
<div
<Layer
className={contentClass}
{...hasScrollingContentProps}
{...rest}
ref={mergeRefs(contentRef, ref)}>
{children}
</div>
</Layer>
);
}
);
Expand Down Expand Up @@ -416,8 +417,9 @@ const ComposedModal = React.forwardRef<HTMLDivElement, ComposedModalProps>(
}

return (
<div
<Layer
{...rest}
level={0}
role="presentation"
ref={ref}
aria-hidden={!open}
Expand Down Expand Up @@ -454,7 +456,7 @@ const ComposedModal = React.forwardRef<HTMLDivElement, ComposedModalProps>(
</button>
)}
</div>
</div>
</Layer>
);
}
);
Expand Down
7 changes: 6 additions & 1 deletion packages/react/src/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ const DatePicker = React.forwardRef(function DatePicker(

// fix datepicker deleting the selectedDate when the calendar closes
const onCalendarClose = (selectedDates, dateStr) => {
endInputField?.current?.focus();
calendarRef?.current?.calendarContainer?.classList.remove('open');
setTimeout(() => {
if (
lastStartValue.current &&
Expand Down Expand Up @@ -667,10 +669,13 @@ const DatePicker = React.forwardRef(function DatePicker(

function handleArrowDown(event) {
if (match(event, keys.Escape)) {
calendar.calendarContainer.classList.remove('open');
calendar?.calendarContainer?.classList.remove('open');
}

if (match(event, keys.ArrowDown)) {
if (event.target == endInputField.current) {
calendar?.calendarContainer?.classList.add('open');
}
const {
calendarContainer,
selectedDateElem: fpSelectedDateElem,
Expand Down
10 changes: 6 additions & 4 deletions packages/react/src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import toggleClass from '../../tools/toggleClass';
import Button from '../Button';
import ButtonSet from '../ButtonSet';
import InlineLoading from '../InlineLoading';
import { Layer } from '../Layer';
import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy';
import wrapFocus, {
wrapFocusWithoutSentinels,
Expand Down Expand Up @@ -529,13 +530,13 @@ const Modal = React.forwardRef(function Modal(
{normalizedSlug}
{!passiveModal && modalButton}
</div>
<div
<Layer
ref={contentRef}
id={modalBodyId}
className={contentClasses}
{...hasScrollingContentProps}>
{children}
</div>
</Layer>
{!passiveModal && (
<ButtonSet className={footerClasses} aria-busy={loadingActive}>
{Array.isArray(secondaryButtons) && secondaryButtons.length <= 2
Expand Down Expand Up @@ -582,8 +583,9 @@ const Modal = React.forwardRef(function Modal(
);

return (
<div
<Layer
{...rest}
level={0}
onKeyDown={handleKeyDown}
onClick={composeEventHandlers([rest?.onClick, handleOnClick])}
onBlur={!focusTrapWithoutSentinels ? handleBlur : () => {}}
Expand Down Expand Up @@ -611,7 +613,7 @@ const Modal = React.forwardRef(function Modal(
Focus sentinel
</span>
)}
</div>
</Layer>
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { getByText, isElementVisible } from '@carbon/test-utils/dom';
import { act, render, screen } from '@testing-library/react';
import React from 'react';
import React, { useState } from 'react';
import MultiSelect from '../';
import {
generateItems,
Expand All @@ -16,6 +16,8 @@ import {
} from '../../ListBox/test-helpers';
import userEvent from '@testing-library/user-event';
import { Slug } from '../../Slug';
import Button from '../../Button';
import ButtonSet from '../../ButtonSet';

const prefix = 'cds';

Expand Down Expand Up @@ -594,4 +596,141 @@ describe('MultiSelect', () => {
);
});
});

describe('Controlled', () => {
const ControlledMultiselect = () => {
const items = generateItems(4, generateGenericItem);
const [selectedItems, setSelectedItems] = useState([]);

const onSelectionChanged = (value) => {
setSelectedItems(value);
};
return (
<>
<MultiSelect
id="test"
titleText="Multiselect title"
label="test-label"
items={items}
selectedItems={selectedItems}
onChange={(data) => onSelectionChanged(data.selectedItems)}
selectionFeedback="top-after-reopen"
/>
<br />
<ButtonSet>
<Button
id="all"
onClick={() =>
setSelectedItems(items.filter((item) => !item.disabled))
}>
Select all
</Button>
<Button
id="clear"
kind="secondary"
onClick={() => setSelectedItems([])}>
Clear
</Button>
</ButtonSet>
</>
);
};

it('should initially render controlled multiselect with a given label', async () => {
const label = 'test-label';
const { container } = render(<ControlledMultiselect />);
await waitForPosition();
// eslint-disable-next-line testing-library/prefer-screen-queries
const labelNode = getByText(container, label);
expect(isElementVisible(labelNode)).toBe(true);

expect(
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
container.querySelector(
'[aria-expanded="true"][aria-haspopup="listbox"]'
)
).toBeNull();
});
it('should allow the items to be controlled from external state', async () => {
const label = 'test-label';
const { container } = render(<ControlledMultiselect />);
const labelNode = getByText(container, label);
expect(isElementVisible(labelNode)).toBe(true);
//select all the items
await userEvent.click(screen.getByText('Select all'));
//open the dropdown to check
const dropwdownNode = screen.getByRole('combobox');
await userEvent.click(dropwdownNode);
// Check if all items are selected
const options = screen.getAllByRole('option');
options.forEach((option) => {
expect(option).toHaveAttribute('aria-selected', 'true');
});

//clear the selection
await userEvent.click(screen.getByText('Clear'));
await userEvent.click(dropwdownNode);
//check if all items are cleared
const items = screen.getAllByRole('option');
items.forEach((option) => {
expect(option).toHaveAttribute('aria-selected', 'false');
});
});
it('should support controlled component functionality with selectedItems and onChange', async () => {
const onChange = jest.fn();
const items = generateItems(4, generateGenericItem);
const { rerender } = render(
<MultiSelect
items={items}
label="test-label"
id="test-id"
selectedItems={[items[0]]}
onChange={onChange}
/>
);

// The selected items should match what's passed into selectedItems
const dropwdownNode = screen.getByRole('combobox');
await userEvent.click(dropwdownNode);
expect(screen.getAllByRole('option')[0]).toHaveAttribute(
'aria-selected',
'true'
);

// onChange should fire for interactions
await userEvent.click(screen.getAllByRole('option')[1]);
expect(onChange).toHaveBeenCalledTimes(1);

// If the onChange event data is not used to update selectedItems, the selection should remain as it was before
expect(screen.getAllByRole('option')[0]).toHaveAttribute(
'aria-selected',
'true'
);
expect(screen.getAllByRole('option')[1]).toHaveAttribute(
'aria-selected',
'false'
);

// Force a re-render with updated selectedItems matching the initial selection and the onChange event data
rerender(
<MultiSelect
items={items}
label="test-label"
id="test-id"
selectedItems={[items[0], items[1]]}
onChange={onChange}
/>
);

// Now both should be selected
expect(screen.getAllByRole('option')[0]).toHaveAttribute(
'aria-selected',
'true'
);
expect(screen.getAllByRole('option')[1]).toHaveAttribute(
'aria-selected',
'true'
);
});
});
});
Loading

0 comments on commit 51480ee

Please sign in to comment.