Skip to content
Merged
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export default {
globalSetup: './global-setup.js',
setupFilesAfterEnv: ['./setupTests.js'],
moduleNameMapper: {
'\\.(css|less)$': 'identity-obj-proxy',
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
// Strip .js extension for FA dynamic imports (webpack needs .js, Jest doesn't)
'^@fortawesome/free-solid-svg-icons/(.+)\\.js$':
'@fortawesome/free-solid-svg-icons/$1',
Expand Down
4 changes: 3 additions & 1 deletion src/lib/components/searchinput/SearchInput.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export type Props = {
searchIconColor?: keyof CoreUITheme;
className?: string;
};
export const SEARCH_INPUT_MIN_WIDTH = convertSizeToRem('1/2');

const SearchInputContainer = styled.div.withConfig({
componentId: 'sc-searchinput',
})<{
Expand All @@ -36,7 +38,7 @@ const SearchInputContainer = styled.div.withConfig({
the layout around it to adapt. */
width: max-content;
max-width: 100%;
min-width: min(${convertSizeToRem('1/2')}, ${(props) => props.$width});
min-width: min(${SEARCH_INPUT_MIN_WIDTH}, ${(props) => props.$width});

input[value] {
max-width: calc(100% - 1rem - ${spacing.f8} - 1rem);
Expand Down
96 changes: 96 additions & 0 deletions src/lib/organisms/attachments/AttachmentTable.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { getWrapper } from '../../testUtils';
import { AttachmentProvider, AttachmentTable } from './AttachmentTable';
import { AttachmentAction, AttachmentOperation } from './AttachmentTypes';

// This table imports the library's own barrels, which re-export the editor and so
// pull CodeMirror's ESM build into a suite that never renders it.
jest.mock('@uiw/react-codemirror', () => ({
__esModule: true,
default: () => null,
}));
jest.mock('codemirror-json-schema', () => ({ jsonSchema: () => [] }));

// jsdom reports 0 for every offsetWidth/scrollWidth; without this stub `ConstrainedText`
// always takes its fitting branch, never the overflow branch a narrow panel renders.
beforeAll(() => {
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
configurable: true,
value: 10,
});
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', {
configurable: true,
value: 1000,
});
});

const { Wrapper } = getWrapper();

const entities = [
{ name: 'User A', id: 'a', type: 'USER' },
{ name: 'User B', id: 'b', type: 'USER' },
];

const renderAttachmentTable = () => {
const onAttachmentsOperationsChanged = jest.fn();

render(
<AttachmentProvider>
<AttachmentTable
entityName={{ singular: 'user', plural: 'users' }}
filteredEntities={{
status: 'success',
data: { number: entities.length, entities },
}}
initiallyAttachedEntities={[]}
initiallyAttachedEntitiesStatus="success"
initialAttachmentOperations={[]}
searchEntityPlaceholder="Search user by name"
onEntitySearchChange={() => {}}
onAttachmentsOperationsChanged={onAttachmentsOperationsChanged}
/>
</AttachmentProvider>,
{ wrapper: Wrapper },
);

const attachedNames = (): string[] =>
onAttachmentsOperationsChanged.mock.calls
.flatMap(([operations]: [AttachmentOperation<string>[]]) => operations)
.filter((operation) => operation.action === AttachmentAction.ADD)
.map((operation) => operation.entity.name);

return { attachedNames };
};

describe('AttachmentTable', () => {
it('attaches the suggestion the user picks', async () => {
const { attachedNames } = renderAttachmentTable();

await userEvent.click(screen.getByRole('searchbox'));
await userEvent.click(await screen.findByText('User B'));

await waitFor(() => expect(attachedNames()).toContain('User B'));
});

it('gives a suggestion its full name when the list is too narrow to show it', async () => {
renderAttachmentTable();

await userEvent.click(screen.getByRole('searchbox'));
await userEvent.hover(await screen.findByText('User B'));

expect(await screen.findByRole('tooltip')).toHaveTextContent('User B');
});

it('attaches nothing when the field loses focus on a highlighted suggestion', async () => {
const { attachedNames } = renderAttachmentTable();

await userEvent.click(screen.getByRole('searchbox'));
await screen.findByText('User B');
await userEvent.keyboard('{ArrowDown}{ArrowDown}');

await userEvent.tab();

expect(attachedNames()).toEqual([]);
});
});
Loading
Loading