Skip to content

Commit 4c0d401

Browse files
angeles-mbniros1
authored andcommitted
[SharedUX] Add unit tests for the feedback snippet component (#235943)
Closes #234445 ## Summary - Added unit tests for the feedback snippet component. - Followed the GIVEN, WHEN, THEN pattern for `feedback_snippet` test file which is the one carrying most of the user interaction logic (inspired by #232925). - Included snapshot tests for both the panel and the button test files. ## Testing You can run them with: `node scripts/jest --config=src/platform/packages/shared/shared-ux/feedback_snippet/jest.config.js` **Test coverage:** (Stories and confetti animation have no tests) File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s -----------------------------------------|---------|----------|---------|---------|------------------------------------------ shared-ux/feedback_snippet/src | 91.66 | 100 | 92.85 | 91.48 | feedback_button.tsx | 100 | 100 | 100 | 100 | feedback_panel.tsx | 100 | 100 | 100 | 100 | feedback_snippet.stories.tsx | 0 | 100 | 0 | 0 | 14-37 feedback_snippet.tsx | 100 | 100 | 100 | 100 | shared-ux/feedback_snippet/src/confetti | 0 | 0 | 0 | 0 | confetti.component.tsx | 0 | 0 | 0 | 0 | 14-38
1 parent b46f769 commit 4c0d401

File tree

9 files changed

+499
-8
lines changed

9 files changed

+499
-8
lines changed

src/platform/packages/shared/shared-ux/feedback_snippet/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@ The component has two main states:
2121
- **Prompt:** The panel shows a custom `promptViewMessage` to gather feedback from the user.
2222
- **Positive:** The panel shows a thank you message and then automatically dismisses itself.
2323
- **Negative:** The panel updates to show a custom `surveyUrl` call-to-action button. The panel remains visible until the user explicitly dismisses it or navigates to the survey (which opens in a new tab).
24+
25+
## Running tests
26+
You can run tests with:
27+
28+
`node scripts/jest --config=src/platform/packages/shared/shared-ux/feedback_snippet/jest.config.js`

src/platform/packages/shared/shared-ux/feedback_snippet/jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
module.exports = {
11-
preset: '@kbn/test/jest_node',
11+
preset: '@kbn/test',
1212
rootDir: '../../../../../..',
1313
roots: ['<rootDir>/src/platform/packages/shared/shared-ux/feedback_snippet'],
1414
};

src/platform/packages/shared/shared-ux/feedback_snippet/src/__snapshots__/feedback_button.test.tsx.snap

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/platform/packages/shared/shared-ux/feedback_snippet/src/__snapshots__/feedback_panel.test.tsx.snap

Lines changed: 188 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import { render, screen } from '@testing-library/react';
11+
import { userEvent } from '@testing-library/user-event';
12+
import React from 'react';
13+
import { FeedbackButton } from './feedback_button';
14+
15+
describe('FeedbackButton', () => {
16+
const handleOpenSurveyMock = jest.fn();
17+
beforeEach(() => {
18+
render(
19+
<FeedbackButton
20+
feedbackButtonMessage={'Got feedback?'}
21+
feedbackSnippetId={'feedbackSnippetTestId'}
22+
handleOpenSurvey={handleOpenSurveyMock}
23+
/>
24+
);
25+
});
26+
27+
it('renders with the expected id', () => {
28+
const button = screen.getByRole('button', { name: 'Feedback button' });
29+
expect(button).toHaveAttribute('id', 'feedbackSnippetTestIdButtonSurveyLink');
30+
expect(button).toMatchSnapshot();
31+
});
32+
33+
it('calls open survey handler when clicked', async () => {
34+
const button = screen.getByRole('button', { name: 'Feedback button' });
35+
await userEvent.click(button);
36+
expect(handleOpenSurveyMock).toHaveBeenCalledTimes(1);
37+
});
38+
});
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import { render, screen } from '@testing-library/react';
11+
import React from 'react';
12+
import { FeedbackPanel } from './feedback_panel';
13+
import type { FeedbackView } from './feedback_snippet';
14+
import { I18nProvider } from '@kbn/i18n-react';
15+
import userEvent from '@testing-library/user-event';
16+
17+
jest.mock('./confetti');
18+
19+
describe('FeedbackPanel', () => {
20+
const handleDismissPanel = jest.fn();
21+
const handleOpenSurveyAndDismissPanel = jest.fn();
22+
const handleNegativeFeedback = jest.fn();
23+
const handlePositiveFeedback = jest.fn();
24+
const testCases: Array<{ view: FeedbackView; expectedElements: Array<() => HTMLElement> }> = [
25+
{
26+
view: 'prompt',
27+
expectedElements: [
28+
() => screen.getByRole('button', { name: 'Thumb down' }),
29+
() => screen.getByRole('button', { name: 'Thumb up' }),
30+
() => screen.getByRole('button', { name: 'Close feedback panel' }),
31+
],
32+
},
33+
{
34+
view: 'positive',
35+
expectedElements: [() => screen.getByTestId('feedbackSnippetPanelPositiveIcon')],
36+
},
37+
{
38+
view: 'negative',
39+
expectedElements: [() => screen.getByRole('button', { name: 'Take quick survey' })],
40+
},
41+
];
42+
const renderPanel = (view: FeedbackView) => {
43+
return render(
44+
<I18nProvider>
45+
<FeedbackPanel
46+
feedbackSnippetId="feedbackSnippetTestId"
47+
feedbackView={view}
48+
promptViewMessage="Was this page helpful?"
49+
handleDismissPanel={handleDismissPanel}
50+
handleOpenSurveyAndDismissPanel={handleOpenSurveyAndDismissPanel}
51+
handleNegativeFeedback={handleNegativeFeedback}
52+
handlePositiveFeedback={handlePositiveFeedback}
53+
/>
54+
</I18nProvider>
55+
);
56+
};
57+
58+
it.each(testCases)(
59+
'renders with the expected inner components based on the feedback view: $view',
60+
async ({ view, expectedElements }) => {
61+
renderPanel(view);
62+
const panel = await screen.findByTestId('feedbackSnippetPanel');
63+
for (const findElement of expectedElements) {
64+
const element = findElement();
65+
expect(element).toBeInTheDocument();
66+
expect(panel.contains(element)).toBe(true);
67+
}
68+
expect(panel).toMatchSnapshot();
69+
}
70+
);
71+
72+
it('calls handlePositiveFeedback when thumb up is clicked', async () => {
73+
renderPanel('prompt');
74+
const button = screen.getByRole('button', { name: 'Thumb up' });
75+
await userEvent.click(button);
76+
expect(handlePositiveFeedback).toHaveBeenCalledTimes(1);
77+
});
78+
79+
it('calls handleNegativeFeedback when thumb down is clicked', async () => {
80+
renderPanel('prompt');
81+
const button = screen.getByRole('button', { name: 'Thumb down' });
82+
await userEvent.click(button);
83+
expect(handleNegativeFeedback).toHaveBeenCalledTimes(1);
84+
});
85+
86+
it('calls handleDismissPanel when close is clicked', async () => {
87+
renderPanel('prompt');
88+
const button = screen.getByRole('button', { name: 'Close feedback panel' });
89+
await userEvent.click(button);
90+
expect(handleDismissPanel).toHaveBeenCalledTimes(1);
91+
});
92+
93+
it('calls handleOpenSurveyAndDismissPanel when survey button is clicked', async () => {
94+
renderPanel('negative');
95+
const button = screen.getByRole('button', { name: 'Take quick survey' });
96+
await userEvent.click(button);
97+
expect(handleOpenSurveyAndDismissPanel).toHaveBeenCalledTimes(1);
98+
});
99+
});

src/platform/packages/shared/shared-ux/feedback_snippet/src/feedback_panel.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,13 @@ export const FeedbackPanel = ({
137137

138138
const positiveFooter = (
139139
<EuiFlexItem grow={false}>
140-
<EuiIcon type="faceHappy" color="success" size="l" aria-label={faceHappyIconLabel} />
140+
<EuiIcon
141+
data-test-subj="feedbackSnippetPanelPositiveIcon"
142+
type="faceHappy"
143+
color="success"
144+
size="l"
145+
aria-label={faceHappyIconLabel}
146+
/>
141147
</EuiFlexItem>
142148
);
143149

0 commit comments

Comments
 (0)