Skip to content

Commit

Permalink
[test] Add tests for the custom slots of TreeItem2 (mui#13314)
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle authored and thomasmoon committed Sep 6, 2024
1 parent e765207 commit d534a3a
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 43 deletions.
3 changes: 3 additions & 0 deletions docs/pages/x/api/tree-view/tree-item-2.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@
"isGlobal": true
}
],
"spread": true,
"themeDefaultProps": true,
"muiName": "MuiTreeItem2",
"forwardsRefTo": "HTMLLIElement",
"filename": "/packages/x-tree-view/src/TreeItem2/TreeItem2.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/x/react-tree-view/rich-tree-view/customization/\">Rich Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/simple-tree-view/customization/\">Simple Tree View - Customization</a></li>\n<li><a href=\"/x/react-tree-view/tree-item-customization/\">Tree Item Customization</a></li></ul>",
Expand Down
46 changes: 3 additions & 43 deletions packages/x-tree-view/src/TreeItem/TreeItem.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,11 @@ import * as React from 'react';
import { expect } from 'chai';
import PropTypes from 'prop-types';
import { createRenderer } from '@mui/internal-test-utils';
import { SimpleTreeViewPluginSignatures } from '@mui/x-tree-view/SimpleTreeView/SimpleTreeView.plugins';
import { TreeItem, treeItemClasses as classes } from '@mui/x-tree-view/TreeItem';
import { TreeViewContextValue } from '@mui/x-tree-view/internals/TreeViewProvider';
import { TreeViewContext } from '@mui/x-tree-view/internals/TreeViewProvider/TreeViewContext';
import { describeConformance } from 'test/utils/describeConformance';
import { describeTreeView } from 'test/utils/tree-view/describeTreeView';

const TEST_TREE_VIEW_CONTEXT_VALUE: TreeViewContextValue<SimpleTreeViewPluginSignatures> = {
instance: {
isItemExpandable: () => false,
isItemExpanded: () => false,
isItemFocused: () => false,
isItemSelected: () => false,
isItemDisabled: (itemId: string | null): itemId is string => !!itemId,
getTreeItemIdAttribute: () => '',
mapFirstCharFromJSX: () => () => {},
canItemBeTabbed: () => false,
} as any,
publicAPI: {
focusItem: () => {},
getItem: () => ({}),
setItemExpansion: () => {},
},
runItemPlugins: () => ({ rootRef: null, contentRef: null }),
wrapItem: ({ children }) => children,
wrapRoot: ({ children }) => children,
disabledItemsFocusable: false,
indentationAtItemLevel: false,
icons: {
slots: {},
slotProps: {},
},
selection: {
multiSelect: false,
checkboxSelection: false,
disableSelection: false,
},
rootRef: {
current: null,
},
};
import { getFakeContextValue } from 'test/utils/tree-view/fakeContextValue';

describeTreeView<[]>('TreeItem component', ({ render, treeItemComponentName }) => {
describe('ContentComponent / ContentProps props (TreeItem only)', () => {
Expand Down Expand Up @@ -94,17 +58,13 @@ describe('<TreeItem />', () => {
inheritComponent: 'li',
wrapMount: (mount) => (item: React.ReactNode) => {
const wrapper = mount(
<TreeViewContext.Provider value={TEST_TREE_VIEW_CONTEXT_VALUE}>
{item}
</TreeViewContext.Provider>,
<TreeViewContext.Provider value={getFakeContextValue()}>{item}</TreeViewContext.Provider>,
);
return wrapper.childAt(0);
},
render: (item) => {
return render(
<TreeViewContext.Provider value={TEST_TREE_VIEW_CONTEXT_VALUE}>
{item}
</TreeViewContext.Provider>,
<TreeViewContext.Provider value={getFakeContextValue()}>{item}</TreeViewContext.Provider>,
);
},
muiName: 'MuiTreeItem',
Expand Down
48 changes: 48 additions & 0 deletions packages/x-tree-view/src/TreeItem2/TreeItem2.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react';
import { createRenderer } from '@mui/internal-test-utils';
import { TreeItem2 } from '@mui/x-tree-view/TreeItem2';
import { treeItemClasses as classes } from '@mui/x-tree-view/TreeItem';
import { TreeViewContext } from '@mui/x-tree-view/internals/TreeViewProvider/TreeViewContext';
import { describeConformance } from 'test/utils/describeConformance';
import { getFakeContextValue } from 'test/utils/tree-view/fakeContextValue';
import { describeSlotsConformance } from 'test/utils/describeSlotsConformance';

describe('<TreeItem2 />', () => {
const { render } = createRenderer();

describeConformance(<TreeItem2 itemId="one" label="one" />, () => ({
classes,
inheritComponent: 'li',
wrapMount: (mount) => (item: React.ReactNode) => {
const wrapper = mount(
<TreeViewContext.Provider value={getFakeContextValue()}>{item}</TreeViewContext.Provider>,
);
return wrapper.childAt(0);
},
render: (item) => {
return render(
<TreeViewContext.Provider value={getFakeContextValue()}>{item}</TreeViewContext.Provider>,
);
},
muiName: 'MuiTreeItem2',
refInstanceof: window.HTMLLIElement,
skip: ['reactTestRenderer', 'componentProp', 'componentsProp', 'themeVariants'],
}));

describeSlotsConformance({
render,
getElement: ({ props, slotName }) => (
<TreeViewContext.Provider
value={getFakeContextValue({ checkboxSelection: slotName === 'checkbox' })}
>
<TreeItem2 itemId="one" label="one" {...props} />
</TreeViewContext.Provider>
),
slots: {
label: { className: classes.label },
iconContainer: { className: classes.iconContainer },
content: { className: classes.content },
checkbox: { className: classes.checkbox },
},
});
});
76 changes: 76 additions & 0 deletions test/utils/describeSlotsConformance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import * as React from 'react';
import { expect } from 'chai';
import createDescribe from '@mui/internal-test-utils/createDescribe';
import { MuiRenderResult } from '@mui/internal-test-utils/createRenderer';

interface DescribeSlotsConformanceParams {
getElement: (params: { slotName: string; props: any }) => React.ReactElement<any>;
render: (node: React.ReactElement) => MuiRenderResult;
slots: { [slotName: string]: { className: string } };
}

export function innerDescribeSlotsConformance(params: DescribeSlotsConformanceParams) {
const { getElement, render, slots } = params;

Object.keys(slots).forEach((slotName) => {
describe(`Slot: ${slotName}`, () => {
it('should replace the default slot when defined', () => {
const slotConfig = slots[slotName];
const response = render(
getElement({
slotName,
props: {
slots: {
[slotName]: React.forwardRef((props, ref: React.Ref<HTMLDivElement>) => (
<div ref={ref} data-testid="custom-slot" />
)),
},
},
}),
);

// Check if the default slot is being rendered
expect(response.container.querySelector(`.${slotConfig.className}`)).to.equal(null);

// Check if the custom slot is being rendered
expect(response.getByTestId('custom-slot')).to.not.equal(null);
});

it('should pass props to the default slot', () => {
const slotConfig = slots[slotName];
const response = render(
getElement({
slotName,
props: {
slotProps: {
[slotName]: { 'data-testid': 'default-slot', className: 'default-slot' },
},
},
}),
);

const slotElement = response.container.querySelector(`.${slotConfig.className}`);

// Check if the default slot is being rendered
expect(slotElement).not.to.equal(null);

// Check if the default slot receives the `data-testid`
expect(slotElement).to.have.attribute('data-testid', 'default-slot');

// Check if the custom class is being applied
expect(slotElement).to.have.class('default-slot');

// Make sure that the default class has not been removed
expect(slotElement).to.have.class(slotConfig.className);
});
});
});
}

/**
* Test the slots of the component.
*/
export const describeSlotsConformance = createDescribe(
'Slots conformance',
innerDescribeSlotsConformance,
);
42 changes: 42 additions & 0 deletions test/utils/tree-view/fakeContextValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { TreeViewContextValue } from '@mui/x-tree-view/internals/TreeViewProvider';
import { SimpleTreeViewPluginSignatures } from '@mui/x-tree-view/SimpleTreeView/SimpleTreeView.plugins';

export const getFakeContextValue = (
features: { checkboxSelection?: boolean } = {},
): TreeViewContextValue<SimpleTreeViewPluginSignatures> => ({
instance: {
isItemExpandable: () => false,
isItemExpanded: () => false,
isItemFocused: () => false,
isItemSelected: () => false,
isItemDisabled: (itemId: string | null): itemId is string => !!itemId,
getTreeItemIdAttribute: () => '',
mapFirstCharFromJSX: () => () => {},
canItemBeTabbed: () => false,
} as any,
publicAPI: {
focusItem: () => {},
getItem: () => ({}),
setItemExpansion: () => {},
},
runItemPlugins: () => ({
rootRef: null,
contentRef: null,
}),
wrapItem: ({ children }) => children,
wrapRoot: ({ children }) => children,
disabledItemsFocusable: false,
indentationAtItemLevel: false,
icons: {
slots: {},
slotProps: {},
},
selection: {
multiSelect: false,
checkboxSelection: features.checkboxSelection ?? false,
disableSelection: false,
},
rootRef: {
current: null,
},
});

0 comments on commit d534a3a

Please sign in to comment.