Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
313 lines
9.8 KiB
TypeScript
313 lines
9.8 KiB
TypeScript
import { mockAppRoot, MockedRouterContext } from '@rocket.chat/mock-providers';
|
|
import { render, screen } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import type { ReactNode } from 'react';
|
|
|
|
import ThreadMetrics from './ThreadMetrics';
|
|
import ThreadMetricsFollow from './ThreadMetricsFollow';
|
|
import ThreadMetricsParticipants from './ThreadMetricsParticipants';
|
|
|
|
const toggleFollowMock =
|
|
(done: jest.DoneCallback | (() => undefined)) =>
|
|
({ mid }: { mid: string }) => {
|
|
expect(mid).toBe('mid');
|
|
done();
|
|
return null;
|
|
};
|
|
|
|
global.ResizeObserver = jest.fn().mockImplementation(() => ({
|
|
observe: jest.fn(),
|
|
unobserve: jest.fn(),
|
|
disconnect: jest.fn(),
|
|
}));
|
|
|
|
const mockRoot = () => {
|
|
const AppRoot = mockAppRoot();
|
|
const buildWithRouter = (navigate: (...args: any[]) => void) => {
|
|
const Wrapper = AppRoot.build();
|
|
return function Mock({ children }: { children: ReactNode }) {
|
|
return (
|
|
<Wrapper>
|
|
<MockedRouterContext router={{ navigate, getRouteName: () => 'thread' as any }}>{children}</MockedRouterContext>
|
|
</Wrapper>
|
|
);
|
|
};
|
|
};
|
|
|
|
return Object.assign(AppRoot, { buildWithRouter });
|
|
};
|
|
|
|
const mockedTranslations = [
|
|
'en',
|
|
'core',
|
|
{
|
|
Follower_one: 'follower',
|
|
Follower_other: 'followers',
|
|
__count__replies__date__: '{{count}} replies {{date}}',
|
|
__count__replies: '{{count}} replies',
|
|
},
|
|
] as const;
|
|
|
|
let inlineSize = 400;
|
|
jest.mock('@rocket.chat/fuselage-hooks', () => {
|
|
const originalModule = jest.requireActual('@rocket.chat/fuselage-hooks');
|
|
return {
|
|
...originalModule,
|
|
useResizeObserver: () => ({ ref: () => undefined, borderBoxSize: { inlineSize } }),
|
|
};
|
|
});
|
|
|
|
describe('Thread Metrics', () => {
|
|
describe('Main component', () => {
|
|
it('should render large followed with 3 participants and unread', async () => {
|
|
const navigateSpy = jest.fn();
|
|
const navigateCallback = (route: any) => {
|
|
navigateSpy(route.name, route.params.rid, route.params.tab, route.params.context);
|
|
};
|
|
|
|
render(
|
|
<ThreadMetrics
|
|
lm={new Date(2024, 6, 1, 0, 0, 0)}
|
|
counter={5}
|
|
participants={['user1', 'user2', 'user3']}
|
|
unread={true}
|
|
mention={false}
|
|
all={false}
|
|
mid='mid'
|
|
rid='rid'
|
|
following={true}
|
|
/>,
|
|
{
|
|
wrapper: mockRoot()
|
|
.withEndpoint(
|
|
'POST',
|
|
'/v1/chat.followMessage',
|
|
toggleFollowMock(() => undefined),
|
|
)
|
|
.withEndpoint(
|
|
'POST',
|
|
'/v1/chat.unfollowMessage',
|
|
toggleFollowMock(() => undefined),
|
|
)
|
|
.withUserPreference('clockMode', 1)
|
|
.withSetting('Message_TimeFormat', 'LT')
|
|
.withTranslations(...mockedTranslations)
|
|
.buildWithRouter(navigateCallback),
|
|
},
|
|
);
|
|
|
|
const followButton = screen.getByTitle('Following');
|
|
expect(followButton).toBeVisible();
|
|
|
|
const badge = screen.getByTitle('Unread');
|
|
expect(badge).toBeVisible();
|
|
|
|
expect(screen.getByTitle('followers')).toBeVisible();
|
|
expect(screen.getByText('3')).toBeVisible();
|
|
|
|
const replyButton = screen.getByText('View_thread');
|
|
expect(replyButton).toBeVisible();
|
|
await userEvent.click(replyButton);
|
|
|
|
expect(navigateSpy).toHaveBeenCalledWith('thread', 'rid', 'thread', 'mid');
|
|
|
|
const threadCount = screen.getByTitle('Last_message__date__');
|
|
expect(threadCount).toHaveTextContent('5 replies July 1st, 2024');
|
|
});
|
|
|
|
it('should render small not followed with 3 participants and unread', async () => {
|
|
const navigateSpy = jest.fn();
|
|
const navigateCallback = (route: any) => {
|
|
navigateSpy(route.name, route.params.rid, route.params.tab, route.params.context);
|
|
};
|
|
inlineSize = 200;
|
|
|
|
render(
|
|
<ThreadMetrics
|
|
lm={new Date(2024, 6, 1, 0, 0, 0)}
|
|
counter={5}
|
|
participants={['user1', 'user2', 'user3']}
|
|
unread={true}
|
|
mention={false}
|
|
all={false}
|
|
mid='mid'
|
|
rid='rid'
|
|
following={false}
|
|
/>,
|
|
{
|
|
wrapper: mockRoot()
|
|
.withEndpoint(
|
|
'POST',
|
|
'/v1/chat.followMessage',
|
|
toggleFollowMock(() => undefined),
|
|
)
|
|
.withEndpoint(
|
|
'POST',
|
|
'/v1/chat.unfollowMessage',
|
|
toggleFollowMock(() => undefined),
|
|
)
|
|
.withUserPreference('clockMode', 1)
|
|
.withSetting('Message_TimeFormat', 'LT')
|
|
.withTranslations(...mockedTranslations)
|
|
.buildWithRouter(navigateCallback),
|
|
},
|
|
);
|
|
const followButton = screen.getByTitle('Not_following');
|
|
expect(followButton).toBeVisible();
|
|
|
|
const badge = screen.getByTitle('Unread');
|
|
expect(badge).toBeVisible();
|
|
|
|
expect(screen.getByTitle('followers')).toBeVisible();
|
|
expect(screen.getByText('3')).toBeVisible();
|
|
|
|
const replyButton = screen.getByText('View_thread');
|
|
expect(replyButton).toBeVisible();
|
|
await userEvent.click(replyButton);
|
|
|
|
expect(navigateSpy).toHaveBeenCalledWith('thread', 'rid', 'thread', 'mid');
|
|
|
|
const threadCount = screen.getByTitle('Last_message__date__');
|
|
expect(threadCount).toHaveTextContent('5 replies');
|
|
});
|
|
});
|
|
|
|
describe('ThreadMetricsFollow', () => {
|
|
it('should render not followed', async () => {
|
|
render(<ThreadMetricsFollow unread={true} mention={false} all={false} mid='mid' rid='rid' following={false} />, {
|
|
wrapper: mockAppRoot()
|
|
.withEndpoint(
|
|
'POST',
|
|
'/v1/chat.followMessage',
|
|
toggleFollowMock(() => undefined),
|
|
)
|
|
.build(),
|
|
});
|
|
const followButton = screen.getByTitle('Not_following');
|
|
expect(followButton).toBeVisible();
|
|
await userEvent.click(followButton);
|
|
});
|
|
it('should render followed', async () => {
|
|
render(<ThreadMetricsFollow unread={true} mention={false} all={false} mid='mid' rid='rid' following={true} />, {
|
|
wrapper: mockAppRoot()
|
|
.withEndpoint(
|
|
'POST',
|
|
'/v1/chat.unfollowMessage',
|
|
toggleFollowMock(() => undefined),
|
|
)
|
|
.build(),
|
|
});
|
|
const followButton = screen.getByTitle('Following');
|
|
expect(followButton).toBeVisible();
|
|
await userEvent.click(followButton);
|
|
});
|
|
it('should render unread badge', () => {
|
|
render(<ThreadMetricsFollow unread={true} mention={false} all={false} mid='mid' rid='rid' following={false} />, {
|
|
wrapper: mockAppRoot().build(),
|
|
});
|
|
const badge = screen.getByTitle('Unread');
|
|
expect(badge).toBeVisible();
|
|
});
|
|
it('should render mention-all badge', () => {
|
|
render(<ThreadMetricsFollow unread={true} mention={false} all={true} mid='mid' rid='rid' following={false} />, {
|
|
wrapper: mockAppRoot().build(),
|
|
});
|
|
const badge = screen.getByTitle('mention-all');
|
|
expect(badge).toBeVisible();
|
|
});
|
|
it('should render Mentions_you badge', () => {
|
|
render(<ThreadMetricsFollow unread={true} mention={true} all={false} mid='mid' rid='rid' following={false} />, {
|
|
wrapper: mockAppRoot().build(),
|
|
});
|
|
const badge = screen.getByTitle('Mentions_you');
|
|
expect(badge).toBeVisible();
|
|
});
|
|
});
|
|
describe('ThreadMetricsParticipants', () => {
|
|
it('should render 1 avatars', () => {
|
|
render(<ThreadMetricsParticipants participants={['user1']} />, {
|
|
wrapper: mockAppRoot()
|
|
.withUserPreference('displayAvatars', true)
|
|
.withTranslations(...mockedTranslations)
|
|
.build(),
|
|
});
|
|
expect(screen.getByTitle('follower')).toBeVisible();
|
|
const avatars = screen.getAllByRole('figure');
|
|
expect(avatars.length).toBe(1);
|
|
expect(avatars.pop()).toBeVisible();
|
|
});
|
|
it('should render 2 avatars', () => {
|
|
render(<ThreadMetricsParticipants participants={['user1', 'user2']} />, {
|
|
wrapper: mockAppRoot()
|
|
.withUserPreference('displayAvatars', true)
|
|
.withTranslations(...mockedTranslations)
|
|
.build(),
|
|
});
|
|
expect(screen.getByTitle('followers')).toBeVisible();
|
|
const avatars = screen.getAllByRole('figure');
|
|
expect(avatars.length).toBe(2);
|
|
avatars.forEach((avatar) => expect(avatar).toBeVisible());
|
|
});
|
|
it('should render 2 avatars and "+1" text', () => {
|
|
render(<ThreadMetricsParticipants participants={['user1', 'user2', 'user3']} />, {
|
|
wrapper: mockAppRoot()
|
|
.withUserPreference('displayAvatars', true)
|
|
.withTranslations(...mockedTranslations)
|
|
.build(),
|
|
});
|
|
expect(screen.getByTitle('followers')).toBeVisible();
|
|
const avatars = screen.getAllByRole('figure');
|
|
expect(avatars.length).toBe(2);
|
|
avatars.forEach((avatar) => expect(avatar).toBeVisible());
|
|
expect(screen.getByText('+1')).toBeVisible();
|
|
});
|
|
it('should render 2 avatars and "+5" text', () => {
|
|
render(<ThreadMetricsParticipants participants={['user1', 'user2', 'user3', 'user4', 'user5', 'user6', 'user7']} />, {
|
|
wrapper: mockAppRoot()
|
|
.withUserPreference('displayAvatars', true)
|
|
.withTranslations(...mockedTranslations)
|
|
.build(),
|
|
});
|
|
expect(screen.getByTitle('followers')).toBeVisible();
|
|
|
|
const avatars = screen.getAllByRole('figure');
|
|
expect(avatars.length).toBe(2);
|
|
avatars.forEach((avatar) => expect(avatar).toBeVisible());
|
|
|
|
expect(screen.getByText('+5')).toBeVisible();
|
|
});
|
|
|
|
it('should render user icon and 1 follower', () => {
|
|
render(<ThreadMetricsParticipants participants={['user1']} />, {
|
|
wrapper: mockAppRoot()
|
|
.withUserPreference('displayAvatars', false)
|
|
.withTranslations(...mockedTranslations)
|
|
.build(),
|
|
});
|
|
const follower = screen.getByTitle('follower');
|
|
expect(follower).toBeVisible();
|
|
|
|
// eslint-disable-next-line testing-library/no-node-access
|
|
expect(follower.querySelector('.rcx-icon--name-user')).toBeVisible();
|
|
|
|
expect(screen.getByText('1')).toBeVisible();
|
|
});
|
|
|
|
it('should render user icon and 5 followers', () => {
|
|
render(<ThreadMetricsParticipants participants={['user1', 'user2', 'user3', 'user4', 'user5']} />, {
|
|
wrapper: mockAppRoot()
|
|
.withUserPreference('displayAvatars', false)
|
|
.withTranslations(...mockedTranslations)
|
|
.build(),
|
|
});
|
|
const follower = screen.getByTitle('followers');
|
|
expect(follower).toBeVisible();
|
|
|
|
// eslint-disable-next-line testing-library/no-node-access
|
|
expect(follower.querySelector('.rcx-icon--name-user')).toBeVisible();
|
|
|
|
expect(screen.getByText('5')).toBeVisible();
|
|
});
|
|
});
|
|
});
|