diff --git a/packages/ui-composer/.storybook/main.ts b/packages/ui-composer/.storybook/main.ts index 8364908884e..561cd8e5766 100644 --- a/packages/ui-composer/.storybook/main.ts +++ b/packages/ui-composer/.storybook/main.ts @@ -4,7 +4,12 @@ import type { StorybookConfig } from '@storybook/react-webpack5'; const config: StorybookConfig = { stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: [getAbsolutePath('@storybook/addon-essentials'), './webpackAddon', getAbsolutePath('@storybook/addon-styling-webpack')], + addons: [ + getAbsolutePath('@storybook/addon-a11y'), + getAbsolutePath('@storybook/addon-essentials'), + './webpackAddon', + getAbsolutePath('@storybook/addon-styling-webpack'), + ], framework: { name: getAbsolutePath('@storybook/react-webpack5'), diff --git a/packages/ui-composer/jest.config.ts b/packages/ui-composer/jest.config.ts new file mode 100644 index 00000000000..1849c7f047e --- /dev/null +++ b/packages/ui-composer/jest.config.ts @@ -0,0 +1,11 @@ +import client from '@rocket.chat/jest-presets/client'; +import type { Config } from 'jest'; + +export default { + preset: client.preset, + setupFilesAfterEnv: [...client.setupFilesAfterEnv], + moduleNameMapper: { + '^react($|/.+)': '/../../node_modules/react$1', + '^react-dom($|/.+)': '/../../node_modules/react-dom$1', + }, +} satisfies Config; diff --git a/packages/ui-composer/package.json b/packages/ui-composer/package.json index 69d17838475..ea2e43f23c8 100644 --- a/packages/ui-composer/package.json +++ b/packages/ui-composer/package.json @@ -15,6 +15,8 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx .", "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", "storybook": "storybook dev -p 6006", + "test": "jest", + "testunit": "jest", "typecheck": "tsc --noEmit" }, "devDependencies": { @@ -23,6 +25,8 @@ "@rocket.chat/eslint-config": "workspace:^", "@rocket.chat/fuselage": "~0.62.0", "@rocket.chat/icons": "^0.42.0", + "@rocket.chat/jest-presets": "workspace:~", + "@storybook/addon-a11y": "^8.6.4", "@storybook/addon-actions": "^8.6.4", "@storybook/addon-docs": "^8.6.4", "@storybook/addon-essentials": "^8.6.4", @@ -30,12 +34,14 @@ "@storybook/addon-webpack5-compiler-babel": "^3.0.5", "@storybook/react": "^8.6.4", "@storybook/react-webpack5": "^8.6.4", + "@types/jest": "~29.5.14", "@types/react": "~18.3.17", "@types/react-dom": "~18.3.5", "eslint": "~8.45.0", "eslint-plugin-react": "~7.37.2", "eslint-plugin-react-hooks": "~5.0.0", "eslint-plugin-storybook": "^0.11.4", + "jest": "~29.7.0", "react": "~18.3.1", "react-dom": "~18.3.1", "storybook": "^8.6.4", diff --git a/packages/ui-composer/src/MessageComposer/MessageComposer.spec.tsx b/packages/ui-composer/src/MessageComposer/MessageComposer.spec.tsx new file mode 100644 index 00000000000..32de84a9685 --- /dev/null +++ b/packages/ui-composer/src/MessageComposer/MessageComposer.spec.tsx @@ -0,0 +1,19 @@ +import { composeStories } from '@storybook/react'; +import { render } from '@testing-library/react'; +import { axe } from 'jest-axe'; + +import * as stories from './MessageComposer.stories'; + +const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName || 'Story', Story]); + +test.each(testCases)(`renders %s without crashing`, async (_storyname, Story) => { + const tree = render(); + expect(tree.baseElement).toMatchSnapshot(); +}); + +test.each(testCases)('%s should have no a11y violations', async (_storyname, Story) => { + const { container } = render(); + + const results = await axe(container); + expect(results).toHaveNoViolations(); +}); diff --git a/packages/ui-composer/src/MessageComposer/MessageComposer.stories.tsx b/packages/ui-composer/src/MessageComposer/MessageComposer.stories.tsx index e777a66553a..b15ddb1a3ea 100644 --- a/packages/ui-composer/src/MessageComposer/MessageComposer.stories.tsx +++ b/packages/ui-composer/src/MessageComposer/MessageComposer.stories.tsx @@ -21,28 +21,25 @@ export default { const MessageToolbarActions = () => ( - + - - - - - - - - - + + + + + + + + - - - - + + + + ); -export const MessageToolberActions: StoryFn = () => ; - -export const _MessageComposer: StoryFn = () => ( +export const Default: StoryFn = () => ( @@ -51,7 +48,9 @@ export const _MessageComposer: StoryFn = () => ( ); -export const MessageComposerWithHints: StoryFn = () => ( +export const ToolbarActions: StoryFn = () => ; + +export const WithHints: StoryFn = () => ( <> = () => ( Editing message - + @@ -75,7 +74,7 @@ export const MessageComposerWithHints: StoryFn = () => ( ); -export const MessageComposerWithSubmitActions: StoryFn = () => ( +export const WithSubmit: StoryFn = () => ( @@ -90,4 +89,4 @@ export const MessageComposerWithSubmitActions: StoryFn = ); -export const MessageComposerLoading: StoryFn = () => ; +export const Loading: StoryFn = () => ; diff --git a/packages/ui-composer/src/MessageComposer/MessageComposerHint.spec.tsx b/packages/ui-composer/src/MessageComposer/MessageComposerHint.spec.tsx new file mode 100644 index 00000000000..57603e72cb3 --- /dev/null +++ b/packages/ui-composer/src/MessageComposer/MessageComposerHint.spec.tsx @@ -0,0 +1,19 @@ +import { composeStories } from '@storybook/react'; +import { render } from '@testing-library/react'; +import { axe } from 'jest-axe'; + +import * as stories from './MessageComposerHint.stories'; + +const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName || 'Story', Story]); + +test.each(testCases)(`renders %s without crashing`, async (_storyname, Story) => { + const tree = render(); + expect(tree.baseElement).toMatchSnapshot(); +}); + +test.each(testCases)('%s should have no a11y violations', async (_storyname, Story) => { + const { container } = render(); + + const results = await axe(container); + expect(results).toHaveNoViolations(); +}); diff --git a/packages/ui-composer/src/MessageComposer/MessageComposerHint.stories.tsx b/packages/ui-composer/src/MessageComposer/MessageComposerHint.stories.tsx index bf423bf4713..ed0e8215097 100644 --- a/packages/ui-composer/src/MessageComposer/MessageComposerHint.stories.tsx +++ b/packages/ui-composer/src/MessageComposer/MessageComposerHint.stories.tsx @@ -4,7 +4,7 @@ import { MessageComposerHint } from '.'; import '@rocket.chat/icons/dist/rocketchat.css'; export default { - title: 'Components/MessageComposer/Hint', + title: 'Components/MessageComposerHint', component: MessageComposerHint, } as Meta; diff --git a/packages/ui-composer/src/MessageComposer/__snapshots__/MessageComposer.spec.tsx.snap b/packages/ui-composer/src/MessageComposer/__snapshots__/MessageComposer.spec.tsx.snap new file mode 100644 index 00000000000..b963e86b2f7 --- /dev/null +++ b/packages/ui-composer/src/MessageComposer/__snapshots__/MessageComposer.spec.tsx.snap @@ -0,0 +1,850 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders Default without crashing 1`] = ` + +
+
+
+