fix: tests (#710)

This commit is contained in:
Daniel Lautzenheiser 2023-04-18 23:05:15 -04:00 committed by GitHub
parent ad694ef56d
commit 6be11c749e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 107 additions and 30 deletions

View File

@ -135,7 +135,6 @@ const NestedCollection = ({ collection, filterTerm }: NestedCollectionProps) =>
const entries = useEntries(collection);
const [treeData, setTreeData] = useState<TreeNodeData[]>(getTreeData(collection, entries));
console.log('TREE DATA', treeData, collection, entries);
const [selected, setSelected] = useState<TreeNodeData | null>(null);
const [useFilter, setUseFilter] = useState(true);

View File

@ -21,6 +21,7 @@ export interface FieldProps {
noPadding?: boolean;
noHightlight?: boolean;
disabled: boolean;
disableClick?: boolean;
}
const Field: FC<FieldProps> = ({
@ -35,13 +36,14 @@ const Field: FC<FieldProps> = ({
noPadding = false,
noHightlight = false,
disabled,
disableClick = false,
}) => {
const finalCursor = useCursor(cursor, disabled);
const hasErrors = useMemo(() => errors.length > 0, [errors.length]);
const handleOnClick = (event: MouseEvent) => {
if (disabled) {
if (disabled || disableClick) {
return;
}

View File

@ -2,7 +2,6 @@ import SelectUnstyled from '@mui/base/SelectUnstyled';
import { KeyboardArrowDown as KeyboardArrowDownIcon } from '@styled-icons/material/KeyboardArrowDown';
import React, { forwardRef, useCallback, useState } from 'react';
import useDebounce from '@staticcms/core/lib/hooks/useDebounce';
import useElementSize from '@staticcms/core/lib/hooks/useElementSize';
import classNames from '@staticcms/core/lib/util/classNames.util';
import { isNotEmpty } from '@staticcms/core/lib/util/string.util';
@ -33,26 +32,32 @@ export interface SelectProps {
required?: boolean;
disabled?: boolean;
onChange: SelectChangeEventHandler;
onOpenChange?: (open: boolean) => void;
}
const Select = forwardRef(
(
{ label, placeholder, value, options, required = false, disabled, onChange }: SelectProps,
{
label,
placeholder,
value,
options,
required = false,
disabled,
onChange,
onOpenChange,
}: SelectProps,
ref: Ref<HTMLButtonElement>,
) => {
const { width } = useElementSize<HTMLButtonElement>(ref);
const [open, setOpen] = useState(false);
const debouncedOpen = useDebounce(open, 200);
const handleOpenChange = useCallback(
(newOpen: boolean) => {
if (debouncedOpen !== open) {
return;
}
setOpen(newOpen);
onOpenChange?.(newOpen);
},
[debouncedOpen, open],
[onOpenChange],
);
const handleButtonClick = useCallback(() => handleOpenChange(!open), [handleOpenChange, open]);

View File

@ -179,7 +179,7 @@ describe('nested.util', () => {
expect(authorsNode.isDir).toBe(true);
expect(authorsNode.isRoot).toBe(false);
expect(authorsNode.path).toBe('/authors');
expect(authorsNode.title).toBe('/authors');
expect(authorsNode.title).toBe('authors');
expect(authorsNode.children.length).toBe(2);
// ROOT > Authors Node > index.md
@ -195,7 +195,7 @@ describe('nested.util', () => {
expect(anAuthorNode.isDir).toBe(true);
expect(anAuthorNode.isRoot).toBe(false);
expect(anAuthorNode.path).toBe('/authors/author-1');
expect(anAuthorNode.title).toBe('/authors/author-1');
expect(anAuthorNode.title).toBe('author-1');
expect(anAuthorNode.children.length).toBe(1);
// ROOT > Authors Node > An Author Node > index.md
@ -211,7 +211,7 @@ describe('nested.util', () => {
expect(postsNode.isDir).toBe(true);
expect(postsNode.isRoot).toBe(false);
expect(postsNode.path).toBe('/posts');
expect(postsNode.title).toBe('/posts');
expect(postsNode.title).toBe('posts');
expect(postsNode.children.length).toBe(3);
// ROOT > Posts Node > index.md
@ -227,7 +227,7 @@ describe('nested.util', () => {
expect(helloWorldNode.isDir).toBe(true);
expect(helloWorldNode.isRoot).toBe(false);
expect(helloWorldNode.path).toBe('/posts/hello-world');
expect(helloWorldNode.title).toBe('/posts/hello-world');
expect(helloWorldNode.title).toBe('hello-world');
expect(helloWorldNode.children.length).toBe(1);
// ROOT > Posts Node > Hello World Node > index.md
@ -243,7 +243,7 @@ describe('nested.util', () => {
expect(newsArticlesNode.isDir).toBe(true);
expect(newsArticlesNode.isRoot).toBe(false);
expect(newsArticlesNode.path).toBe('/posts/news');
expect(newsArticlesNode.title).toBe('/posts/news');
expect(newsArticlesNode.title).toBe('news');
expect(newsArticlesNode.children.length).toBe(2);
// ROOT > Posts Node > Hello World Node > index.md
@ -259,7 +259,7 @@ describe('nested.util', () => {
expect(helloWorldNewsNode.isDir).toBe(true);
expect(helloWorldNewsNode.isRoot).toBe(false);
expect(helloWorldNewsNode.path).toBe('/posts/news/hello-world-news');
expect(helloWorldNewsNode.title).toBe('/posts/news/hello-world-news');
expect(helloWorldNewsNode.title).toBe('hello-world-news');
expect(helloWorldNewsNode.children.length).toBe(1);
// ROOT > Posts Node > Hello World Node > Hello World News Node > index.md

View File

@ -1,5 +1,5 @@
import trim from 'lodash/trim';
import { basename, dirname, extname, join, sep } from 'path';
import { basename, dirname, extname, join } from 'path';
import { sanitizeSlug } from '../urlHelper';
import { selectEntryCollectionTitle, selectFolderEntryExtension } from './collection.util';
@ -104,9 +104,9 @@ export function getTreeData<EF extends BaseField>(
const dirs = entriesObj.reduce((acc, entry) => {
let dir: string | undefined = dirname(entry.path);
while (dir && !acc[dir] && dir !== rootFolder) {
const parts: string[] = dir.split(sep);
const parts: string[] = dir.split('/');
acc[dir] = parts.pop();
dir = parts.length ? parts.join(sep) : undefined;
dir = parts.length ? parts.join('/') : undefined;
}
return acc;
}, {} as Record<string, string | undefined>);

View File

@ -112,6 +112,11 @@ const SelectControl: FC<WidgetControlProps<string | number | (string | number)[]
return `${internalValue}`;
}, [isMultiple, internalValue]);
const [open, setOpen] = useState(false);
const handleOpenChange = useCallback((open: boolean) => {
setOpen(open);
}, []);
return (
<Field
inputRef={ref}
@ -122,6 +127,7 @@ const SelectControl: FC<WidgetControlProps<string | number | (string | number)[]
forSingleList={forSingleList}
cursor="pointer"
disabled={disabled}
disableClick={open}
>
<Select
label={
@ -146,6 +152,7 @@ const SelectControl: FC<WidgetControlProps<string | number | (string | number)[]
required={field.required}
disabled={disabled}
onChange={handleChange}
onOpenChange={handleOpenChange}
/>
</Field>
);

View File

@ -2,8 +2,8 @@
* @jest-environment jsdom
*/
import '@testing-library/jest-dom';
import { act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { act, waitFor } from '@testing-library/react';
import { mockSelectField } from '@staticcms/test/data/fields.mock';
import { createWidgetControlHarness } from '@staticcms/test/harnesses/widget.harness';
@ -82,6 +82,7 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl();
@ -94,6 +95,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-Option 1';
const option2 = 'select-option-Option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected
@ -180,6 +186,7 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockNumberSelectField });
@ -192,6 +199,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected
@ -263,11 +275,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMixedSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -275,6 +287,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-Option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected
@ -359,11 +376,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockStringSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -371,6 +388,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-option 1';
const option2 = 'select-option-option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected
@ -455,11 +477,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockNumberSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -467,6 +489,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected
@ -551,11 +578,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMixedSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -563,6 +590,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected
@ -635,11 +667,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMultiStringSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -647,6 +679,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-Option 1';
const option2 = 'select-option-Option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected
@ -733,11 +770,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMultiNumberSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -745,6 +782,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected
@ -831,11 +873,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMultiMixedSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -843,6 +885,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-Option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected
@ -933,11 +980,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMultiStringSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -945,6 +992,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-option 1';
const option2 = 'select-option-option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected
@ -1035,11 +1087,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMultiNumberSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -1047,6 +1099,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected
@ -1137,11 +1194,11 @@ describe(SelectControl.name, () => {
it('should call onChange when text input changes', async () => {
const {
getByTestId,
queryByTestId,
props: { onChange },
} = renderControl({ field: mockMultiNumberSelectField });
const input = getByTestId('select-input');
await act(async () => {
await userEvent.click(input);
});
@ -1149,6 +1206,11 @@ describe(SelectControl.name, () => {
const option1 = 'select-option-1';
const option2 = 'select-option-option 2';
await waitFor(() => {
expect(queryByTestId(option1)).toBeInTheDocument();
expect(queryByTestId(option2)).toBeInTheDocument();
});
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected

View File

@ -1,3 +1,5 @@
module.exports = async () => {
process.env.TZ = 'US/Hawaii';
};
globalThis.IS_REACT_ACT_ENVIRONMENT = true;