Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@internxt/ui",
"version": "0.1.10",
"version": "0.1.11",
"description": "Library of Internxt components",
"repository": {
"type": "git",
Expand Down
29 changes: 29 additions & 0 deletions src/components/mail/cheaps/user/UserCheap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Avatar } from '@/components/avatar';

interface UserCheapProps {
fullName: string;
email: string;
avatar?: string;
}

/**
* A cheap user component to render a user's information.
*
* @param {UserCheapProps} props - The props object.
* @param {string} props.fullName - The user's full name.
* @param {string} props.email - The user's email address.
* @param {string} [props.avatar] - The user's avatar URL. If not provided, the avatar will be generated from the user's name.
*/
const UserCheap = ({ fullName, email, avatar }: UserCheapProps) => (
<div className="flex flex-row gap-2 border max-w-64 bg-surface w-full border-gray-10 shadow-subtle rounded-lg">
<div className="flex flex-row w-full gap-2 p-4">
<Avatar src={avatar} fullName={fullName} diameter={40} />
<div className="flex flex-col min-w-0">
<p className="font-medium text-gray-100 truncate">{fullName}</p>
<p className="text-sm text-gray-50 truncate">{email}</p>
</div>
</div>
</div>
);

export default UserCheap;
49 changes: 49 additions & 0 deletions src/components/mail/cheaps/user/__test__/UserCheap.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import UserCheap from '../UserCheap';

const defaultProps = {
fullName: 'John Doe',
email: 'john.doe@internxt.com',
};

describe('UserCheap', () => {
it('should match snapshot', () => {
const component = render(<UserCheap {...defaultProps} />);
expect(component).toMatchSnapshot();
});

it('should render full name and email', () => {
render(<UserCheap {...defaultProps} />);

expect(screen.getByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('john.doe@internxt.com')).toBeInTheDocument();
});

it('should render with avatar when src is provided', () => {
const avatar = 'https://example.com/avatar.jpg';
const component = render(<UserCheap {...defaultProps} avatar={avatar} />);
expect(component).toMatchSnapshot();
});

it('should render without avatar when src is not provided', () => {
const component = render(<UserCheap {...defaultProps} />);
expect(component).toMatchSnapshot();
});

it('should truncate long full name', () => {
const longName = 'A Very Long Name That Should Be Truncated In The Component';
render(<UserCheap fullName={longName} email={defaultProps.email} />);

const nameEl = screen.getByText(longName);
expect(nameEl.className).toContain('truncate');
});

it('should truncate long email', () => {
const longEmail = 'a.very.long.email.address.that.should.be.truncated@internxt.com';
render(<UserCheap fullName={defaultProps.fullName} email={longEmail} />);

const emailEl = screen.getByText(longEmail);
expect(emailEl.className).toContain('truncate');
});
});
Loading
Loading