Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove clear button from chat UI #66

Merged
merged 1 commit into from
Nov 15, 2024
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
35 changes: 1 addition & 34 deletions src/components/Sidebar/index.jsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import React, { useRef, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import {
Button,
Icon,
IconButton,
} from '@openedx/paragon';
import { Close } from '@openedx/paragon/icons';

import { clearMessages } from '../../data/thunks';
import { OPTIMIZELY_PROMPT_EXPERIMENT_KEY } from '../../data/optimizely';
import showSurvey from '../../utils/surveyMonkey';

import APIError from '../APIError';
import ChatBox from '../ChatBox';
import Disclosure from '../Disclosure';
import MessageForm from '../MessageForm';
import './Sidebar.scss';
import { usePromptExperimentDecision } from '../../experiments';

const Sidebar = ({
courseId,
Expand All @@ -32,14 +27,6 @@ const Sidebar = ({
messageList,
} = useSelector(state => state.learningAssistant);
const chatboxContainerRef = useRef(null);
const dispatch = useDispatch();

const [decision] = usePromptExperimentDecision();
const { enabled: enabledExperiment, variationKey } = decision || {};
const experimentPayload = enabledExperiment ? {
experiment_name: OPTIMIZELY_PROMPT_EXPERIMENT_KEY,
variation_key: variationKey,
} : {};

// this use effect is intended to scroll to the bottom of the chat window, in the case
// that a message is larger than the chat window height.
Expand Down Expand Up @@ -83,14 +70,6 @@ const Sidebar = ({
}
};

const handleClearMessages = () => {
dispatch(clearMessages());
sendTrackEvent('edx.ui.lms.learning_assistant.clear', {
course_id: courseId,
...experimentPayload,
});
};

const getMessageForm = () => (
<MessageForm courseId={courseId} shouldAutofocus unitId={unitId} />
);
Expand Down Expand Up @@ -120,18 +99,6 @@ const Sidebar = ({
)
}
{getMessageForm()}
<div className="d-flex justify-content-start">
<Button
className="clear mx-2 mb-2 border-0"
onClick={handleClearMessages}
aria-label="clear"
variant="primary"
type="button"
data-testid="sidebar-clear-btn"
>
Clear
</Button>
</div>
</div>
);

Expand Down
41 changes: 0 additions & 41 deletions src/components/Sidebar/index.test.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React from 'react';
import { screen, act } from '@testing-library/react';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';

import { usePromptExperimentDecision } from '../../experiments';
import { render as renderComponent } from '../../utils/utils.test';
import { initialState } from '../../data/slice';
import { OPTIMIZELY_PROMPT_EXPERIMENT_KEY, OPTIMIZELY_PROMPT_EXPERIMENT_VARIATION_KEYS } from '../../data/optimizely';
import showSurvey from '../../utils/surveyMonkey';

import Sidebar from '.';
Expand Down Expand Up @@ -35,11 +33,6 @@ jest.mock('../../experiments', () => ({
usePromptExperimentDecision: jest.fn(),
}));

const clearMessagesAction = 'clear-messages-action';
jest.mock('../../data/thunks', () => ({
clearMessages: () => 'clear-messages-action',
}));

const defaultProps = {
courseId: 'some-course-id',
isOpen: true,
Expand Down Expand Up @@ -88,17 +81,6 @@ describe('<Sidebar />', () => {
render(undefined, { disclosureAcknowledged: true });
expect(screen.queryByTestId('sidebar-xpert')).toBeInTheDocument();
});

it('should dispatch clearMessages() and call sendTrackEvent() with the expected props on clear', () => {
render(undefined, { disclosureAcknowledged: true });

act(() => {
screen.queryByTestId('sidebar-clear-btn').click();
});

expect(mockDispatch).toHaveBeenCalledWith(clearMessagesAction);
expect(sendTrackEvent).toHaveBeenCalledWith('edx.ui.lms.learning_assistant.clear', { course_id: defaultProps.courseId });
});
});

describe('when it\'s not open', () => {
Expand Down Expand Up @@ -133,28 +115,5 @@ describe('<Sidebar />', () => {

expect(showSurvey).toHaveBeenCalled();
});

it('should dispatch clearMessages() and call sendTrackEvent() with the expected props on clear', () => {
usePromptExperimentDecision.mockReturnValue([{
enabled: true,
variationKey: OPTIMIZELY_PROMPT_EXPERIMENT_VARIATION_KEYS.UPDATED_PROMPT,
}]);

render(undefined, {
...defaultState,
disclosureAcknowledged: true,
});

act(() => {
screen.queryByTestId('sidebar-clear-btn').click();
});

expect(mockDispatch).toHaveBeenCalledWith(clearMessagesAction);
expect(sendTrackEvent).toHaveBeenCalledWith('edx.ui.lms.learning_assistant.clear', {
course_id: defaultProps.courseId,
experiment_name: OPTIMIZELY_PROMPT_EXPERIMENT_KEY,
variation_key: OPTIMIZELY_PROMPT_EXPERIMENT_VARIATION_KEYS.UPDATED_PROMPT,
});
});
});
});
6 changes: 0 additions & 6 deletions src/data/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ export const learningAssistantSlice = createSlice({
setMessageList: (state, { payload }) => {
state.messageList = payload.messageList;
},
resetMessages: (state) => {
state.currentMessage = '';
state.messageList = [];
state.apiError = false;
},
setApiError: (state) => {
state.apiError = true;
},
Expand All @@ -56,7 +51,6 @@ export const {
setCurrentMessage,
clearCurrentMessage,
setMessageList,
resetMessages,
setApiError,
setApiIsLoading,
resetApiError,
Expand Down
8 changes: 0 additions & 8 deletions src/data/thunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { fetchChatResponse, fetchLearningAssistantMessageHistory, fetchLearningA
import {
setCurrentMessage,
clearCurrentMessage,
resetMessages,
setMessageList,
setApiError,
setApiIsLoading,
Expand Down Expand Up @@ -74,13 +73,6 @@ export function getChatResponse(courseId, unitId, promptExperimentVariationKey =
};
}

export function clearMessages() {
return (dispatch) => {
dispatch(resetMessages());
dispatch(resetApiError());
};
}

export function getLearningAssistantMessageHistory(courseId) {
return async (dispatch) => {
dispatch(setApiIsLoading(true));
Expand Down
61 changes: 0 additions & 61 deletions src/widgets/Xpert.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const assertSidebarElementsNotInDOM = () => {

expect(screen.queryByRole('button', { name: 'submit' })).not.toBeInTheDocument();
expect(screen.queryByTestId('close-button')).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'clear' })).not.toBeInTheDocument();
};

beforeEach(() => {
Expand Down Expand Up @@ -115,7 +114,6 @@ test('clicking the call to action opens the sidebar', async () => {
expect(screen.getByRole('textbox')).toBeVisible();
expect(screen.getByRole('button', { name: 'submit' })).toBeVisible();
expect(screen.getByTestId('close-button')).toBeVisible();
expect(screen.getByRole('button', { name: 'clear' })).toBeVisible();

// assert that text input has focus
expect(screen.getByRole('textbox')).toHaveFocus();
Expand All @@ -135,7 +133,6 @@ test('clicking the toggle button opens the sidebar', async () => {
expect(screen.getByRole('textbox')).toBeVisible();
expect(screen.getByRole('button', { name: 'submit' })).toBeVisible();
expect(screen.getByTestId('close-button')).toBeVisible();
expect(screen.getByRole('button', { name: 'clear' })).toBeVisible();

// assert that text input has focus
expect(screen.getByRole('textbox')).toHaveFocus();
Expand Down Expand Up @@ -190,34 +187,6 @@ test('response text appears as message in the sidebar', async () => {
await screen.findByText(responseMessage.content);
expect(screen.getByText(responseMessage.content)).toBeInTheDocument();
});
test('clicking the clear button clears messages in the sidebar', async () => {
const user = userEvent.setup();
const userMessage = 'Hello, Xpert!';

// re-mock the fetchChatResponse API function so that we can assert that the
// responseMessage appears in the DOM and then is successfully cleared
const responseMessage = createRandomResponseForTesting();
jest.spyOn(api, 'fetchChatResponse').mockImplementation(() => responseMessage);

render(<Xpert courseId={courseId} contentToolsEnabled={false} unitId={unitId} />, { preloadedState: initialState });

// wait for button to appear
await screen.findByTestId('toggle-button');

await user.click(screen.queryByTestId('toggle-button'));

// type the user message
const input = screen.getByRole('textbox');
await user.type(input, userMessage);
await user.click(screen.getByRole('button', { name: 'submit' }));

await screen.findByText(responseMessage.content);

await user.click(screen.getByRole('button', { name: 'clear' }));

expect(screen.queryByText(userMessage)).not.toBeInTheDocument();
expect(screen.queryByText(responseMessage.content)).not.toBeInTheDocument();
});
test('clicking the close button closes the sidebar', async () => {
const user = userEvent.setup();
render(<Xpert courseId={courseId} contentToolsEnabled={false} unitId={unitId} />, { preloadedState: initialState });
Expand Down Expand Up @@ -307,35 +276,6 @@ test('error message should disappear when dismissed', async () => {
await user.click(screen.getByText('Dismiss'));
expect(screen.queryByText('Please try again by sending another question.')).not.toBeInTheDocument();
});
test('error message should disappear when messages cleared', async () => {
const user = userEvent.setup();

const errorState = {
learningAssistant: {
currentMessage: '',
messageList: [],
apiIsLoading: false,
apiError: true,
// TEMPORARY: This is simply to ensure that the tests pass by hiding the disclosure.
// I will remove this and write tests in a future pull request.
disclosureAcknowledged: true,
sidebarIsOpen: false,
},
};
render(<Xpert courseId={courseId} contentToolsEnabled={false} unitId={unitId} />, { preloadedState: errorState });

// wait for button to appear
await screen.findByTestId('toggle-button');

await user.click(screen.queryByTestId('toggle-button'));

// assert that error message exists
expect(screen.queryByText('Please try again by sending another question.')).toBeInTheDocument();

// clear messages, assert that error message disappears
await user.click(screen.getByText('Clear'));
expect(screen.queryByText('Please try again by sending another question.')).not.toBeInTheDocument();
});
test('popup modal should open chat', async () => {
const user = userEvent.setup();
window.localStorage.clear();
Expand All @@ -357,7 +297,6 @@ test('popup modal should open chat', async () => {
expect(screen.getByRole('textbox')).toBeVisible();
expect(screen.getByRole('button', { name: 'submit' })).toBeVisible();
expect(screen.getByTestId('close-button')).toBeVisible();
expect(screen.getByRole('button', { name: 'clear' })).toBeVisible();
});
test('popup modal should close and display CTA', async () => {
const user = userEvent.setup();
Expand Down