Skip to content

Commit

Permalink
fix(utils): correctly check type of element (#1560)
Browse files Browse the repository at this point in the history
  • Loading branch information
ValeraS authored May 2, 2024
1 parent 911624f commit c854f4f
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
76 changes: 76 additions & 0 deletions src/components/utils/__tests__/isOfType.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';

import {render, screen} from '../../../../test-utils/utils';
import {isOfType} from '../isOfType';

function Test(props: React.PropsWithChildren<{matcher: (c: unknown) => boolean}>) {
const child = React.Children.only(props.children);

return props.matcher(child) ? 'correct' : 'wrong';
}

describe('isOfType', () => {
test('should match type of component', () => {
const Component = () => null;

render(
<Test matcher={isOfType(Component)}>
<Component />
</Test>,
);
expect(screen.getByText('correct')).toBeVisible();
});
test('should match displayName', () => {
const Component = () => null;
Component.displayName = 'comp1';
const Component2 = () => null;
Component2.displayName = 'comp1';

render(
<Test matcher={isOfType(Component)}>
<Component2 />
</Test>,
);
expect(screen.getByText('correct')).toBeVisible();
});
test('should not match if type and displayName do not match', () => {
const Component = () => null;
Component.displayName = 'comp1';
const Component2 = () => null;
Component2.displayName = 'comp2';

render(
<Test matcher={isOfType(Component)}>
<Component2 />
</Test>,
);
expect(screen.getByText('wrong')).toBeVisible();
});
test('should not match if type do not match and displayName is absent', () => {
const Component = () => null;
const Component2 = () => null;

render(
<Test matcher={isOfType(Component)}>
<Component2 />
</Test>,
);
expect(screen.getByText('wrong')).toBeVisible();
});
test('should match type of builtin component', () => {
render(
<Test matcher={isOfType('svg')}>
<svg />
</Test>,
);
expect(screen.getByText('correct')).toBeVisible();
});
test('should not match if type of builtin component is different', () => {
render(
<Test matcher={isOfType('svg')}>
<button />
</Test>,
);
expect(screen.getByText('wrong')).toBeVisible();
});
});
19 changes: 12 additions & 7 deletions src/components/utils/isOfType.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import React from 'react';

export function isOfType<P = {}>(Component: React.ComponentType<P>) {
export function isOfType<P = {}>(Component: React.ComponentType<P> | string) {
return function isMatching(
component: React.ReactNode,
): component is React.ReactElement<P, typeof React.Component> {
component: unknown,
): component is React.ReactElement<P, typeof Component> {
if (!React.isValidElement(component)) {
return false;
}

const {type} = component;
if (type === Component) {
return true;
}

if (typeof Component === 'string' || typeof type === 'string') {
return false;
}

return (
type === React.Component ||
(type as React.ComponentType).displayName === Component.displayName
);
const displayName = (type as React.ComponentType).displayName;
return Boolean(displayName && displayName === Component.displayName);
};
}

0 comments on commit c854f4f

Please sign in to comment.