Skip to content

Commit

Permalink
Add tests for react packages
Browse files Browse the repository at this point in the history
  • Loading branch information
ericfennis committed Mar 18, 2024
1 parent 4b67599 commit c56e29d
Show file tree
Hide file tree
Showing 39 changed files with 578 additions and 151 deletions.
53 changes: 53 additions & 0 deletions packages/lucide-preact/src/Icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { h, toChildArray } from 'preact';
import defaultAttributes from './defaultAttributes';
import { IconNode, LucideProps } from './createLucideIcon';

interface IconComponentProps extends LucideProps {
iconNode: IconNode
}

/**
* Lucide icon component
*
* @component Icon
* @param {object} props
* @param {string} props.color - The color of the icon
* @param {number} props.size - The size of the icon
* @param {number} props.strokeWidth - The stroke width of the icon
* @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width
* @param {string} props.class - The class name of the icon
* @param {IconNode} props.children - The children of the icon
* @param {IconNode} props.iconNode - The icon node of the icon
*
* @returns {ForwardRefExoticComponent} LucideIcon
*/
const Icon = ({
color = 'currentColor',
size = 24,
strokeWidth = 2,
absoluteStrokeWidth,
children,
iconNode,
class: classes = '',
...rest
}: IconComponentProps) =>
h(
'svg',
{
...defaultAttributes,
width: String(size),
height: size,
stroke: color,
['stroke-width' as 'strokeWidth']: absoluteStrokeWidth
? (Number(strokeWidth) * 24) / Number(size)
: strokeWidth,
class: ['lucide', classes].join(' '),
...rest,
},
[
...iconNode.map(([tag, attrs]) => h(tag, attrs)),
...toChildArray(children)
],
);

export default Icon
33 changes: 13 additions & 20 deletions packages/lucide-preact/src/createLucideIcon.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type FunctionComponent, h, type JSX, toChildArray } from 'preact';
import defaultAttributes from './defaultAttributes';
import { toKebabCase } from '@lucide/shared';
import { type FunctionComponent, h, type JSX } from 'preact';
import { mergeClasses, toKebabCase } from '@lucide/shared';
import Icon from './Icon';

export type IconNode = [elementName: keyof JSX.IntrinsicElements, attrs: Record<string, string>][];

Expand All @@ -21,28 +21,21 @@ export type LucideIcon = FunctionComponent<LucideProps>;
*/
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
const Component = ({
color = 'currentColor',
size = 24,
strokeWidth = 2,
absoluteStrokeWidth,
children,
class: classes = '',
...rest
children,
...props
}: LucideProps) =>
h(
'svg',
Icon,
{
...defaultAttributes,
width: String(size),
height: size,
stroke: color,
['stroke-width' as 'strokeWidth']: absoluteStrokeWidth
? (Number(strokeWidth) * 24) / Number(size)
: strokeWidth,
class: ['lucide', `lucide-${toKebabCase(iconName)}`, classes].join(' '),
...rest,
...props,
iconNode,
class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
`lucide-${toKebabCase(iconName)}`,
classes
),
},
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
children,
);

Component.displayName = `${iconName}`;
Expand Down
2 changes: 1 addition & 1 deletion packages/lucide-preact/src/useIconComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const useIconComponent = <Icons extends Record<string, IconNode>>(icons: Icons)
)

if (!iconNodesHasCorrectType) {
console.error('[lucide-preact]: Passed icons object has incorrect type')
console.error('[lucide-preact]: Passed icons object has an incorrect children type')
}

const iconComponents = iconNodeEntries.reduce((acc, [iconName, iconNode]) => {
Expand Down
33 changes: 33 additions & 0 deletions packages/lucide-preact/tests/Icon.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { describe, it, expect } from 'vitest';
import { render } from '@testing-library/preact';

import { airVent } from './testIconNodes';
import Icon from '../src/Icon';

describe('Using Icon Component', () => {
it('should render icon based on a iconNode', async () => {
const { container } = render(
<Icon
iconNode={airVent}
size={48}
stroke="red"
absoluteStrokeWidth
/>,
);

expect( container.firstChild ).toBeDefined()
});

it('should render icon and match snapshot', async () => {
const { container } = render(
<Icon
iconNode={airVent}
size={48}
stroke="red"
absoluteStrokeWidth
/>,
);

expect( container.firstChild ).toMatchSnapshot();
});
})
29 changes: 29 additions & 0 deletions packages/lucide-preact/tests/__snapshots__/Icon.spec.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Using Icon Component > should render icon and match snapshot 1`] = `
<svg
class="lucide "
fill="none"
height="48"
stroke="red"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1"
viewBox="0 0 24 24"
width="48"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"
/>
<path
d="M6 8h12"
/>
<path
d="M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"
/>
<path
d="M6.6 15.6A2 2 0 1 0 10 17v-5"
/>
</svg>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Using createLucideIcon > should create a component from an iconNode 1`] = `
<svg
class="lucide lucide-air-vent"
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"
/>
<path
d="M6 8h12"
/>
<path
d="M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"
/>
<path
d="M6.6 15.6A2 2 0 1 0 10 17v-5"
/>
</svg>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
stroke-width="4"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-grid3x3 "
data-testid="grid-icon"
class="lucide lucide-grid3x3"
>
<rect width="18"
height="18"
Expand Down Expand Up @@ -41,8 +40,7 @@ exports[`Using lucide icon components > should not scale the strokeWidth when ab
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-grid3x3 "
data-testid="grid-icon"
class="lucide lucide-grid3x3"
>
<rect width="18"
height="18"
Expand Down Expand Up @@ -72,7 +70,7 @@ exports[`Using lucide icon components > should render an component 1`] = `
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-grid3x3 "
class="lucide lucide-grid3x3"
>
<rect width="18"
height="18"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Using iconNode component generator > should create a component from an iconNode 1`] = `
<svg
class="lucide lucide-air-vent "
class="lucide lucide-air-vent"
fill="none"
height="24"
stroke="currentColor"
Expand Down Expand Up @@ -31,7 +31,7 @@ exports[`Using iconNode component generator > should create a component from an
exports[`Using iconNode component generator > should create multiple components 1`] = `
<div>
<svg
class="lucide lucide-air-vent "
class="lucide lucide-air-vent"
fill="none"
height="24"
stroke="currentColor"
Expand All @@ -56,7 +56,7 @@ exports[`Using iconNode component generator > should create multiple components
/>
</svg>
<svg
class="lucide lucide-coffee "
class="lucide lucide-coffee"
fill="none"
height="24"
stroke="currentColor"
Expand Down
15 changes: 15 additions & 0 deletions packages/lucide-preact/tests/createLucideIcon.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, it, expect } from 'vitest';
import { createLucideIcon } from '../src/lucide-preact';
import { airVent } from './testIconNodes';
import { render } from '@testing-library/preact'

describe('Using createLucideIcon', () => {
it('should create a component from an iconNode', () => {
const AirVent = createLucideIcon('AirVent', airVent)

const { container } = render( <AirVent/> );

expect( container.firstChild ).toMatchSnapshot();
expect( container.firstChild ).toBeDefined();
});
})
50 changes: 31 additions & 19 deletions packages/lucide-preact/tests/lucide-preact.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, it, expect } from 'vitest';
import { render, cleanup } from '@testing-library/preact';
import { Pen, Edit2, Grid, Droplet } from '../src/lucide-preact';
import defaultAttributes from '../src/defaultAttributes';

type AttributesAssertion = { attributes: Record<string, { value: string }> };

Expand All @@ -11,30 +12,43 @@ describe('Using lucide icon components', () => {
expect(container.innerHTML).toMatchSnapshot();
});

it('should render the icon with the default attributes', () => {
const { container } = render(<Grid />);

const SVGElement = container.firstElementChild

expect(SVGElement).toHaveAttribute('xmlns', defaultAttributes.xmlns);
expect(SVGElement).toHaveAttribute('width', String(defaultAttributes.width));
expect(SVGElement).toHaveAttribute('height', String(defaultAttributes.height));
expect(SVGElement).toHaveAttribute('viewBox', defaultAttributes.viewBox);
expect(SVGElement).toHaveAttribute('fill', defaultAttributes.fill);
expect(SVGElement).toHaveAttribute('stroke', defaultAttributes.stroke);
expect(SVGElement).toHaveAttribute('stroke-width', String(defaultAttributes['stroke-width']));
expect(SVGElement).toHaveAttribute('stroke-linecap', defaultAttributes['stroke-linecap']);
expect(SVGElement).toHaveAttribute('stroke-linejoin', defaultAttributes['stroke-linejoin']);
});

it('should adjust the size, stroke color and stroke width', () => {
const testId = 'grid-icon';
const { container, getByTestId } = render(
const { container } = render(
<Grid
data-testid={testId}
size={48}
stroke="red"
strokeWidth={4}
/>,
);

const { attributes } = getByTestId(testId) as unknown as AttributesAssertion;
expect(attributes.stroke.value).toBe('red');
expect(attributes.width.value).toBe('48');
expect(attributes.height.value).toBe('48');
expect(attributes['stroke-width'].value).toBe('4');
const SVGElement = container.firstElementChild

expect(SVGElement).toHaveAttribute('stroke', 'red');
expect(SVGElement).toHaveAttribute('width', '48');
expect(SVGElement).toHaveAttribute('height', '48');
expect(SVGElement).toHaveAttribute('stroke-width', '4');
expect(container.innerHTML).toMatchSnapshot();
});

it('should render the alias icon', () => {
const testId = 'pen-icon';
const { container } = render(
<Pen
data-testid={testId}
size={48}
stroke="red"
strokeWidth={4}
Expand All @@ -47,7 +61,6 @@ describe('Using lucide icon components', () => {

const { container: Edit2Container } = render(
<Edit2
data-testid={testId}
size={48}
stroke="red"
strokeWidth={4}
Expand All @@ -58,22 +71,21 @@ describe('Using lucide icon components', () => {
});

it('should not scale the strokeWidth when absoluteStrokeWidth is set', () => {
const testId = 'grid-icon';
const { container, getByTestId } = render(
const { container } = render(
<Grid
data-testid={testId}
size={48}
stroke="red"
absoluteStrokeWidth
/>,
);

const { attributes } = getByTestId(testId) as unknown as AttributesAssertion;
const SVGElement = container.firstElementChild

expect(SVGElement).toHaveAttribute('stroke', 'red');
expect(SVGElement).toHaveAttribute('width', '48');
expect(SVGElement).toHaveAttribute('height', '48');
expect(SVGElement).toHaveAttribute('stroke-width', '1');

expect(attributes.stroke.value).toBe('red');
expect(attributes.width.value).toBe('48');
expect(attributes.height.value).toBe('48');
expect(attributes['stroke-width'].value).toBe('1');
expect(container.innerHTML).toMatchSnapshot();
});

Expand Down
1 change: 1 addition & 0 deletions packages/lucide-react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@lucide/build-icons": "workspace:*",
"@lucide/shared": "workspace:*",
"@testing-library/jest-dom": "^6.1.6",
"@testing-library/react": "^14.1.2",
"@types/prop-types": "^15.7.5",
Expand Down
Loading

0 comments on commit c56e29d

Please sign in to comment.