diff --git a/webapp/packages/core-blocks/src/Cell.test.tsx b/webapp/packages/core-blocks/src/Cell.test.tsx new file mode 100644 index 0000000000..0aeeb2f9c2 --- /dev/null +++ b/webapp/packages/core-blocks/src/Cell.test.tsx @@ -0,0 +1,59 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { waitFor } from '@testing-library/react'; + +import { createApp, renderInApp } from '@cloudbeaver/tests-runner'; + +import { Cell } from './Cell'; + +const app = createApp(); + +describe('Cell', () => { + it('should render children correctly', async () => { + const { getByText } = renderInApp(Test Children, app); + const text = await waitFor(() => getByText('Test Children')); + + expect(text).toBeInTheDocument(); + }); + + it('should render before element correctly', async () => { + const { getByText } = renderInApp(Before Element}>Test Children, app); + + const beforeText = await waitFor(() => getByText('Before Element')); + expect(beforeText).toBeInTheDocument(); + }); + + it('should render after element correctly', async () => { + const { getByText } = renderInApp(After Element}>Test Children, app); + + const afterText = await waitFor(() => getByText('After Element')); + expect(afterText).toBeInTheDocument(); + }); + + it('should render after and before elements correctly', async () => { + const { getByText } = renderInApp( + Before Element} after={After Element}> + Test Children + , + app, + ); + + const afterText = await waitFor(() => getByText('After Element')); + const beforeText = await waitFor(() => getByText('Before Element')); + + expect(beforeText).toBeInTheDocument(); + expect(afterText).toBeInTheDocument(); + }); + + it('should render description element correctly', async () => { + const { getByText } = renderInApp(Description Element}>Test Children, app); + + const description = await waitFor(() => getByText('Description Element')); + expect(description).toBeInTheDocument(); + }); +}); diff --git a/webapp/packages/core-blocks/src/Link.test.tsx b/webapp/packages/core-blocks/src/Link.test.tsx new file mode 100644 index 0000000000..00547c4cc3 --- /dev/null +++ b/webapp/packages/core-blocks/src/Link.test.tsx @@ -0,0 +1,63 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { fireEvent, queryByAttribute, waitFor } from '@testing-library/react'; + +import { createApp, renderInApp } from '@cloudbeaver/tests-runner'; + +import { Link } from './Link'; + +const app = createApp(); + +describe('Link', () => { + it('should render link and children correctly', async () => { + const { getByText } = renderInApp(Test Link, app); + const linkElement = await waitFor(() => getByText('Test Link')); + + expect(linkElement.tagName).toBe('A'); + expect(linkElement).toBeInTheDocument(); + }); + + it('should display the indicator icon when indicator is true', async () => { + const { container } = renderInApp( + + Test Link + , + app, + ); + + const icon = await waitFor(() => queryByAttribute('href', container, /external-link/i)); + expect(icon).toBeInTheDocument(); + }); + + it('should apply the className correctly', async () => { + const { getByText } = renderInApp( + + Test Link + , + app, + ); + + const linkContainer = await waitFor(() => getByText('Test Link').closest('div')); + expect(linkContainer).toHaveClass('custom-class'); + }); + + it('should handle onClick event', async () => { + const handleClick = jest.fn(); + const { getByText } = renderInApp( + + Test Link + , + app, + ); + + const linkElement = await waitFor(() => getByText('Test Link')); + fireEvent.click(linkElement); + + expect(handleClick).toHaveBeenCalled(); + }); +}); diff --git a/webapp/packages/core-blocks/src/StatusMessage.test.tsx b/webapp/packages/core-blocks/src/StatusMessage.test.tsx new file mode 100644 index 0000000000..e04f56f8a3 --- /dev/null +++ b/webapp/packages/core-blocks/src/StatusMessage.test.tsx @@ -0,0 +1,64 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { fireEvent, queryByAttribute, waitFor } from '@testing-library/react'; + +import { coreDialogsManifest } from '@cloudbeaver/core-dialogs'; +import { ENotificationType } from '@cloudbeaver/core-events'; +import { coreLocalizationManifest } from '@cloudbeaver/core-localization'; +import { createApp, renderInApp } from '@cloudbeaver/tests-runner'; + +import { StatusMessage } from './StatusMessage'; + +const app = createApp(coreLocalizationManifest, coreDialogsManifest); + +describe('StatusMessage', () => { + it('should display an error icon and message when type is error', async () => { + const message = 'test_error'; + const { container, getByTitle } = renderInApp(, app); + const title = await waitFor(() => getByTitle(message)); + const icon = await waitFor(() => queryByAttribute('src', container, /error/i)); + + expect(title).toBeInTheDocument(); + expect(icon).toBeInTheDocument(); + }); + + it('should display a success icon and message when type is success', async () => { + const message = 'test_success'; + const { container, getByTitle } = renderInApp(, app); + const title = await waitFor(() => getByTitle(message)); + const icon = await waitFor(() => queryByAttribute('src', container, /success/i)); + + expect(title).toBeInTheDocument(); + expect(icon).toBeInTheDocument(); + }); + + it('should display an error message when no message is provided', async () => { + const { getByText } = renderInApp(, app); + const message = await waitFor(() => getByText('Test error')); + + expect(message).toBeInTheDocument(); + }); + + it('should call onShowDetails when link is clicked', async () => { + const onShowDetails = jest.fn(); + const message = 'test_message_with_details'; + const { getByText } = renderInApp(, app); + const link = await waitFor(() => getByText(message)); + + fireEvent.click(link); + expect(onShowDetails).toHaveBeenCalled(); + }); + + it('should display multiple messages joined by comma', async () => { + const messages = ['message_one', 'message_two']; + const { getByText } = renderInApp(, app); + const message = await waitFor(() => getByText('message_one, message_two')); + + expect(message).toBeInTheDocument(); + }); +}); diff --git a/webapp/packages/core-blocks/src/Text.test.tsx b/webapp/packages/core-blocks/src/Text.test.tsx new file mode 100644 index 0000000000..31cf85b16e --- /dev/null +++ b/webapp/packages/core-blocks/src/Text.test.tsx @@ -0,0 +1,40 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { waitFor } from '@testing-library/react'; + +import { createApp, renderInApp } from '@cloudbeaver/tests-runner'; + +import { Text } from './Text'; + +const app = createApp(); + +describe('Text Component', () => { + it('renders children correctly', async () => { + const { getByText } = renderInApp(Hello World, app); + const text = await waitFor(() => getByText('Hello World')); + expect(text).toBeInTheDocument(); + }); + + it('applies custom className', () => { + const { container } = renderInApp(Hello World, app); + expect(container.getElementsByClassName('custom-class')).toHaveLength(1); + }); + + it('passes HTML attributes correctly', () => { + const { container } = renderInApp( + + Hello World + , + app, + ); + + const div = container.firstChild; + expect(div).toHaveAttribute('id', 'custom-id'); + expect(div).toHaveAttribute('data-testid', 'custom-testid'); + }); +}); diff --git a/webapp/packages/core-blocks/src/Text.tsx b/webapp/packages/core-blocks/src/Text.tsx index 38289b0faf..83b7e8b138 100644 --- a/webapp/packages/core-blocks/src/Text.tsx +++ b/webapp/packages/core-blocks/src/Text.tsx @@ -7,8 +7,6 @@ */ import { observer } from 'mobx-react-lite'; -interface Props extends React.HTMLAttributes {} - -export const Text: React.FC = observer(function Text({ children, ...rest }) { +export const Text: React.FC> = observer(function Text({ children, ...rest }) { return
{children}
; }); diff --git a/webapp/packages/core-blocks/src/TextPlaceholder.test.tsx b/webapp/packages/core-blocks/src/TextPlaceholder.test.tsx new file mode 100644 index 0000000000..2e7a55f07c --- /dev/null +++ b/webapp/packages/core-blocks/src/TextPlaceholder.test.tsx @@ -0,0 +1,27 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { waitFor } from '@testing-library/react'; + +import { createApp, renderInApp } from '@cloudbeaver/tests-runner'; + +import { TextPlaceholder } from './TextPlaceholder'; + +const app = createApp(); + +describe('TextPlaceholder Component', () => { + it('renders children correctly', async () => { + const { getByText } = renderInApp(Hello World, app); + const text = await waitFor(() => getByText('Hello World')); + expect(text).toBeInTheDocument(); + }); + + it('applies custom className', () => { + const { container } = renderInApp(Hello World, app); + expect(container.getElementsByClassName('custom-class')).toHaveLength(1); + }); +}); diff --git a/webapp/packages/core-blocks/src/TimerIcon.test.tsx b/webapp/packages/core-blocks/src/TimerIcon.test.tsx new file mode 100644 index 0000000000..a596842d04 --- /dev/null +++ b/webapp/packages/core-blocks/src/TimerIcon.test.tsx @@ -0,0 +1,42 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2024 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { queryByAttribute, waitFor } from '@testing-library/react'; + +import { createApp, renderInApp } from '@cloudbeaver/tests-runner'; + +import { TimerIcon } from './TimerIcon'; + +const app = createApp(); + +describe('TimerIcon', () => { + it('renders correctly with state "play" and interval 30', async () => { + const { getByText, container } = renderInApp(, app); + const text = await waitFor(() => getByText('30')); + const name = await waitFor(() => queryByAttribute('href', container, '/icons/timer-play_m.svg#root')); + + expect(name).toBeInTheDocument(); + expect(text).toBeInTheDocument(); + }); + + it('renders correctly with state "stop" and interval 60', async () => { + const { getByText, container } = renderInApp(, app); + const text = await waitFor(() => getByText('60')); + const name = await waitFor(() => queryByAttribute('href', container, '/icons/timer-stop_m.svg#root')); + + expect(name).toBeInTheDocument(); + expect(text).toBeInTheDocument(); + }); + + it('passes HTML attributes correctly', () => { + const { container } = renderInApp(, app); + + const div = container.firstChild; + expect(div).toHaveAttribute('id', 'custom-id'); + expect(div).toHaveAttribute('data-testid', 'custom-testid'); + }); +}); diff --git a/webapp/packages/core-blocks/src/TimerIcon.tsx b/webapp/packages/core-blocks/src/TimerIcon.tsx index f87620d475..0de5860e34 100644 --- a/webapp/packages/core-blocks/src/TimerIcon.tsx +++ b/webapp/packages/core-blocks/src/TimerIcon.tsx @@ -10,7 +10,7 @@ import type React from 'react'; import { Icon } from './Icon'; import { s } from './s'; -import style from './TimerIcon.module.css'; +import classes from './TimerIcon.module.css'; import { useS } from './useS'; interface Props { @@ -19,7 +19,7 @@ interface Props { } export const TimerIcon = observer>(function TimerIcon({ state, interval, ...rest }) { - const styles = useS(style); + const styles = useS(classes); return (