diff --git a/src/data/api.js b/src/data/api.js index 2ff6a906..4450e269 100644 --- a/src/data/api.js +++ b/src/data/api.js @@ -23,22 +23,7 @@ async function fetchChatResponse(courseId, messageList, unitId, customQueryParam return data; } -async function fetchLearningAssistantEnabled(courseId) { - const url = new URL(`${getConfig().CHAT_RESPONSE_URL}/${courseId}/enabled`); - - const { data } = await getAuthenticatedHttpClient().get(url.href); - return data; -} - -async function fetchLearningAssistantMessageHistory(courseId) { - const url = new URL(`${getConfig().CHAT_RESPONSE_URL}/${courseId}/history`); - - const { data } = await getAuthenticatedHttpClient().get(url.href); - return data; -} - -async function fetchLearningAssistantAuditTrial(courseId) { - // TODO: Insert correct URL once get endpoint is implemented. +async function fetchLearningAssistantSummary(courseId) { const url = new URL(`${getConfig().CHAT_RESPONSE_URL}/${courseId}/summary`); const { data } = await getAuthenticatedHttpClient().get(url.href); @@ -47,7 +32,5 @@ async function fetchLearningAssistantAuditTrial(courseId) { export { fetchChatResponse, - fetchLearningAssistantAuditTrial, - fetchLearningAssistantEnabled, - fetchLearningAssistantMessageHistory, + fetchLearningAssistantSummary, }; diff --git a/src/data/api.test.js b/src/data/api.test.js index 7b747a5a..d558122e 100644 --- a/src/data/api.test.js +++ b/src/data/api.test.js @@ -1,7 +1,7 @@ /* eslint-disable no-import-assign */ import * as auth from '@edx/frontend-platform/auth'; -import { fetchLearningAssistantMessageHistory } from './api'; +import { fetchLearningAssistantSummary } from './api'; jest.mock('@edx/frontend-platform/auth'); @@ -16,38 +16,45 @@ describe('API', () => { jest.restoreAllMocks(); }); - describe('fetchLearningAssistantMessageHistory()', () => { - const fakeCourseId = 'course-v1:edx+test+23'; - const apiPayload = [ - { - role: 'user', - content: 'Marco', - timestamp: '2024-11-04T19:05:07.403363Z', + describe('fetchLearningAssistantSummary()', () => { + const courseId = 'course-v1:edx+test+23'; + const apiPayload = { + enabled: true, + message_history: [ + { + role: 'user', + content: 'Marco', + timestamp: '2024-11-04T19:05:07.403363Z', + }, + { + role: 'assistant', + content: 'Polo', + timestamp: '2024-11-04T19:05:21.357636Z', + }, + ], + audit_trial: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', }, - { - role: 'assistant', - content: 'Polo', - timestamp: '2024-11-04T19:05:21.357636Z', - }, - ]; + }; - const fakeGet = jest.fn(async () => ({ + const mockGet = jest.fn(async () => ({ data: apiPayload, - catch: () => {}, + catch: () => { }, })); beforeEach(() => { auth.getAuthenticatedHttpClient = jest.fn(() => ({ - get: fakeGet, + get: mockGet, })); }); it('should call the endpoint and process the results', async () => { - const response = await fetchLearningAssistantMessageHistory(fakeCourseId); + const response = await fetchLearningAssistantSummary(courseId); expect(response).toEqual(apiPayload); - expect(fakeGet).toHaveBeenCalledTimes(1); - expect(fakeGet).toHaveBeenCalledWith(`${CHAT_RESPONSE_URL}/${fakeCourseId}/history`); + expect(mockGet).toHaveBeenCalledTimes(1); + expect(mockGet).toHaveBeenCalledWith(`${CHAT_RESPONSE_URL}/${courseId}/summary`); }); }); }); diff --git a/src/data/slice.js b/src/data/slice.js index c479822f..39e06ec7 100644 --- a/src/data/slice.js +++ b/src/data/slice.js @@ -50,8 +50,6 @@ export const learningAssistantSlice = createSlice({ }, setAuditTrial: (state, { payload }) => { state.auditTrial = payload; - // state.auditTrial.startDate = payload.start_date; - // state.auditTrial.expirationDate = payload.expiration_date; }, }, }); diff --git a/src/data/thunks.js b/src/data/thunks.js index 996c9f44..501e588b 100644 --- a/src/data/thunks.js +++ b/src/data/thunks.js @@ -4,9 +4,7 @@ import { getAuthenticatedUser } from '@edx/frontend-platform/auth'; import trackChatBotMessageOptimizely from '../utils/optimizelyExperiment'; import { fetchChatResponse, - fetchLearningAssistantMessageHistory, - fetchLearningAssistantEnabled, - fetchLearningAssistantAuditTrial, + fetchLearningAssistantSummary, } from './api'; import { setCurrentMessage, @@ -79,33 +77,6 @@ export function getChatResponse(courseId, unitId, promptExperimentVariationKey = }; } -export function getLearningAssistantMessageHistory(courseId) { - return async (dispatch) => { - dispatch(setApiIsLoading(true)); - - try { - const rawMessageList = await fetchLearningAssistantMessageHistory(courseId); - - if (rawMessageList.length) { - const messageList = rawMessageList - .map(({ timestamp, ...msg }) => ({ - ...msg, - timestamp: new Date(timestamp), // Parse ISO time to Date() - })); - - dispatch(setMessageList({ messageList })); - - // If it has chat history, then we assume the user already aknowledged. - dispatch(setDisclosureAcknowledged(true)); - } - } catch (e) { - // If fetching the messages fail, we just won't show it. - } - - dispatch(setApiIsLoading(false)); - }; -} - export function updateCurrentMessage(content) { return (dispatch) => { dispatch(setCurrentMessage({ currentMessage: content })); @@ -130,32 +101,46 @@ export function updateSidebarIsOpen(isOpen) { }; } -export function getIsEnabled(courseId) { +export function getLearningAssistantSummary(courseId) { return async (dispatch) => { + dispatch(setApiIsLoading(true)); + try { - const data = await fetchLearningAssistantEnabled(courseId); + const data = await fetchLearningAssistantSummary(courseId); + + // Enabled dispatch(setIsEnabled(data.enabled)); - } catch (error) { - dispatch(setApiError()); - } - }; -} -export function getAuditTrial(courseId) { - return async (dispatch) => { - try { - const data = await fetchLearningAssistantAuditTrial(courseId); - console.log("DATA:", data) - console.log("data.start_date:", data.start_date) - console.log("data.expiration_date:", data.expiration_date) - // If returned data is not empty - if (Object.keys(data).length !== 0) { // eslint-disable-line no-undef - console.log("SETTING!") - // TODO: FIGURE OUT how to sync the data from Michael's PR into this MFEs state... - dispatch(setAuditTrial(data)); + // Message History + const rawMessageList = data.message_history; + + // If returned message history data is not empty + if (rawMessageList.length) { + const messageList = rawMessageList + .map(({ timestamp, ...msg }) => ({ + ...msg, + // NOTE to self: can't store Date() objects in store: https://github.com/reduxjs/redux-toolkit/issues/456 + timestamp: new Date(timestamp).toString(), // Parse ISO time to Date() + })); + + dispatch(setMessageList({ messageList })); + + // If it has chat history, then we assume the user already aknowledged. + dispatch(setDisclosureAcknowledged(true)); + } + + // Audit Trial + const auditTrial = data.audit_trial; + + // If returned audit trial data is not empty + if (Object.keys(auditTrial).length !== 0) { // eslint-disable-line no-undef + dispatch(setAuditTrial(auditTrial)); } } catch (error) { + // NOTE: When used to not show if fetching the messages failed + // But we do know since this endpoint is combined. dispatch(setApiError()); } + dispatch(setApiIsLoading(false)); }; } diff --git a/src/data/thunks.test.js b/src/data/thunks.test.js index 2a5039aa..75d1d576 100644 --- a/src/data/thunks.test.js +++ b/src/data/thunks.test.js @@ -1,6 +1,6 @@ -import { fetchLearningAssistantMessageHistory } from './api'; +import { fetchLearningAssistantSummary } from './api'; -import { getLearningAssistantMessageHistory } from './thunks'; +import { getLearningAssistantSummary } from './thunks'; jest.mock('./api'); @@ -9,118 +9,201 @@ describe('Thunks unit tests', () => { afterEach(() => jest.resetAllMocks()); - describe('getLearningAssistantMessageHistory()', () => { - const fakeCourseId = 'course-v1:edx+test+23'; - - describe('when returning results', () => { - const apiResponse = [ - { - role: 'user', - content: 'Marco', - timestamp: '2024-11-04T19:05:07.403363Z', - }, - { - role: 'assistant', - content: 'Polo', - timestamp: '2024-11-04T19:05:21.357636Z', + describe('getLearningAssistantSummary()', () => { + const courseId = 'course-v1:edx+test+23'; + + it('with message_history and audit_trial data returned, call all expected dispatches', async () => { + const apiResponse = { + enabled: true, + message_history: [ + { + role: 'user', + content: 'Marco', + timestamp: '2024-11-04T19:05:07.403363Z', + }, + { + role: 'assistant', + content: 'Polo', + timestamp: '2024-11-04T19:05:21.357636Z', + }, + ], + audit_trial: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', }, - ]; + }; + + fetchLearningAssistantSummary.mockResolvedValue(apiResponse); - beforeEach(() => { - fetchLearningAssistantMessageHistory.mockResolvedValue(apiResponse); + await getLearningAssistantSummary(courseId)(dispatch); + + expect(dispatch).toHaveBeenNthCalledWith(1, { + type: 'learning-assistant/setApiIsLoading', + payload: true, }); - it('should set the loading state, fetch, parse and set the messages and remove the loading state', async () => { - await getLearningAssistantMessageHistory(fakeCourseId)(dispatch); + expect(fetchLearningAssistantSummary).toHaveBeenCalledWith(courseId); - expect(dispatch).toHaveBeenNthCalledWith(1, { - type: 'learning-assistant/setApiIsLoading', - payload: true, - }); + expect(dispatch).toHaveBeenNthCalledWith(2, { + type: 'learning-assistant/setIsEnabled', + payload: true, + }); - expect(fetchLearningAssistantMessageHistory).toHaveBeenCalledWith(fakeCourseId); + expect(dispatch).toHaveBeenNthCalledWith(3, { + type: 'learning-assistant/setMessageList', + payload: { + messageList: apiResponse.message_history.map(({ timestamp, ...msg }) => ({ + ...msg, + timestamp: new Date(timestamp).toString(), // Parse ISO time to Date() + })), + }, + }); - expect(dispatch).toHaveBeenNthCalledWith(2, { - type: 'learning-assistant/setMessageList', - payload: { - messageList: apiResponse.map(({ timestamp, ...msg }) => ({ - ...msg, - timestamp: new Date(timestamp), // Parse ISO time to Date() - })), - }, - }); + expect(dispatch).toHaveBeenNthCalledWith(4, { + type: 'learning-assistant/setDisclosureAcknowledged', + payload: true, + }); - expect(dispatch).toHaveBeenNthCalledWith(3, { - type: 'learning-assistant/setDisclosureAcknowledged', - payload: true, - }); + expect(dispatch).toHaveBeenNthCalledWith(5, { + type: 'learning-assistant/setAuditTrial', + payload: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', + }, + }); - expect(dispatch).toHaveBeenNthCalledWith(4, { - type: 'learning-assistant/setApiIsLoading', - payload: false, - }); + expect(dispatch).toHaveBeenNthCalledWith(6, { + type: 'learning-assistant/setApiIsLoading', + payload: false, }); }); - describe('when returning no messages', () => { - const apiResponse = []; + it('with no message_history data returned, do not call message history related dispatches', async () => { + const apiResponse = { + enabled: true, + message_history: [], + audit_trial: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', + }, + }; + + fetchLearningAssistantSummary.mockResolvedValue(apiResponse); - beforeEach(() => { - fetchLearningAssistantMessageHistory.mockResolvedValue(apiResponse); + await getLearningAssistantSummary(courseId)(dispatch); + + expect(dispatch).toHaveBeenNthCalledWith(1, { + type: 'learning-assistant/setApiIsLoading', + payload: true, }); - it('should only set and remove the loading state', async () => { - await getLearningAssistantMessageHistory(fakeCourseId)(dispatch); + expect(fetchLearningAssistantSummary).toHaveBeenCalledWith(courseId); - expect(dispatch).toHaveBeenNthCalledWith(1, { - type: 'learning-assistant/setApiIsLoading', - payload: true, - }); + expect(dispatch).toHaveBeenNthCalledWith(2, { + type: 'learning-assistant/setIsEnabled', + payload: true, + }); - expect(fetchLearningAssistantMessageHistory).toHaveBeenCalledWith(fakeCourseId); + expect(dispatch).not.toHaveBeenCalledWith( + expect.objectContaining({ type: 'learning-assistant/setMessageList' }), + ); - expect(dispatch).not.toHaveBeenCalledWith( - expect.objectContaining({ type: 'learning-assistant/setMessageList' }), - ); + expect(dispatch).not.toHaveBeenCalledWith( + expect.objectContaining({ type: 'learning-assistant/setDisclosureAcknowledged' }), + ); - expect(dispatch).not.toHaveBeenCalledWith( - expect.objectContaining({ type: 'learning-assistant/setDisclosureAcknowledged' }), - ); + expect(dispatch).toHaveBeenNthCalledWith(3, { + type: 'learning-assistant/setAuditTrial', + payload: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', + }, + }); - expect(dispatch).toHaveBeenNthCalledWith(2, { - type: 'learning-assistant/setApiIsLoading', - payload: false, - }); + expect(dispatch).toHaveBeenNthCalledWith(4, { + type: 'learning-assistant/setApiIsLoading', + payload: false, }); }); - describe('when throwing on fetching', () => { - beforeEach(() => { - fetchLearningAssistantMessageHistory.mockRejectedValue('Whoopsie!'); + it('with no audit_trial data returned, do not call audit trial dispatch', async () => { + const apiResponse = { + enabled: true, + message_history: [ + { + role: 'user', + content: 'Marco', + timestamp: '2024-11-04T19:05:07.403363Z', + }, + { + role: 'assistant', + content: 'Polo', + timestamp: '2024-11-04T19:05:21.357636Z', + }, + ], + audit_trial: {}, + }; + + fetchLearningAssistantSummary.mockResolvedValue(apiResponse); + + await getLearningAssistantSummary(courseId)(dispatch); + + expect(dispatch).toHaveBeenNthCalledWith(1, { + type: 'learning-assistant/setApiIsLoading', + payload: true, + }); + + expect(fetchLearningAssistantSummary).toHaveBeenCalledWith(courseId); + + expect(dispatch).toHaveBeenNthCalledWith(2, { + type: 'learning-assistant/setIsEnabled', + payload: true, + }); + + expect(dispatch).toHaveBeenNthCalledWith(3, { + type: 'learning-assistant/setMessageList', + payload: { + messageList: apiResponse.message_history.map(({ timestamp, ...msg }) => ({ + ...msg, + timestamp: new Date(timestamp).toString(), // Parse ISO time to Date() + })), + }, }); - it('should only set and remove the loading state', async () => { - await getLearningAssistantMessageHistory(fakeCourseId)(dispatch); + expect(dispatch).toHaveBeenNthCalledWith(4, { + type: 'learning-assistant/setDisclosureAcknowledged', + payload: true, + }); - expect(dispatch).toHaveBeenNthCalledWith(1, { - type: 'learning-assistant/setApiIsLoading', - payload: true, - }); + expect(dispatch).toHaveBeenNthCalledWith(5, { + type: 'learning-assistant/setApiIsLoading', + payload: false, + }); + }); + + it('when throwing on fetching, should set the loading state and throw error', async () => { + fetchLearningAssistantSummary.mockRejectedValue('Whoopsie!'); + + await getLearningAssistantSummary(courseId)(dispatch); + + expect(dispatch).toHaveBeenNthCalledWith(1, { + type: 'learning-assistant/setApiIsLoading', + payload: true, + }); - expect(fetchLearningAssistantMessageHistory).toHaveBeenCalledWith(fakeCourseId); + expect(fetchLearningAssistantSummary).toHaveBeenCalledWith(courseId); - expect(dispatch).not.toHaveBeenCalledWith( - expect.objectContaining({ type: 'learning-assistant/setMessageList' }), - ); + expect(dispatch).not.toHaveBeenCalledWith( + expect.objectContaining({ type: 'learning-assistant/setMessageList' }), + ); - expect(dispatch).not.toHaveBeenCalledWith( - expect.objectContaining({ type: 'learning-assistant/setDisclosureAcknowledged' }), - ); + expect(dispatch).not.toHaveBeenCalledWith( + expect.objectContaining({ type: 'learning-assistant/setDisclosureAcknowledged' }), + ); - expect(dispatch).toHaveBeenNthCalledWith(2, { - type: 'learning-assistant/setApiIsLoading', - payload: false, - }); + expect(dispatch).toHaveBeenNthCalledWith(2, { + type: 'learning-assistant/setApiError', + // payload: false, }); }); }); diff --git a/src/hooks/index.js b/src/hooks/index.js deleted file mode 100644 index bfa4b76e..00000000 --- a/src/hooks/index.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -export { useMessageHistory } from './message-history'; diff --git a/src/hooks/message-history.js b/src/hooks/message-history.js deleted file mode 100644 index c27d5f46..00000000 --- a/src/hooks/message-history.js +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -import { useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { getLearningAssistantMessageHistory } from '../data/thunks'; - -export const useMessageHistory = (courseId) => { - const dispatch = useDispatch(); - const { isEnabled } = useSelector(state => state.learningAssistant); - - useEffect(() => { - if (!courseId || !isEnabled) { return; } - - dispatch(getLearningAssistantMessageHistory(courseId)); - }, [dispatch, isEnabled, courseId]); -}; diff --git a/src/hooks/message-history.test.js b/src/hooks/message-history.test.js deleted file mode 100644 index fe1352b1..00000000 --- a/src/hooks/message-history.test.js +++ /dev/null @@ -1,57 +0,0 @@ -import { renderHook } from '@testing-library/react-hooks'; // eslint-disable-line import/no-unresolved - -import { useSelector } from 'react-redux'; -import { useMessageHistory } from './message-history'; -import { getLearningAssistantMessageHistory } from '../data/thunks'; - -const mockDispatch = jest.fn(); -jest.mock('react-redux', () => ({ - ...jest.requireActual('react-redux'), - useSelector: jest.fn(), - useDispatch: () => mockDispatch, -})); - -const getLearningAssistantMessageHistorySignature = { getLearningAssistantMessageHistory: 'getLearningAssistantMessageHistory' }; -jest.mock('../data/thunks', () => ({ - getLearningAssistantMessageHistory: jest.fn().mockReturnValue(getLearningAssistantMessageHistorySignature), -})); - -describe('Learning Assistant Message History Hooks', () => { - afterEach(() => { - jest.resetAllMocks(); - }); - - describe('useMessageHistory()', () => { - let hook; - const fakeCourseId = 'course-v1:edx+test+23'; - - const renderTestHook = (courseId, isEnabled) => { - const mockedStoreState = { learningAssistant: { isEnabled } }; - useSelector.mockImplementation(selector => selector(mockedStoreState)); - hook = renderHook(() => useMessageHistory(courseId)); - return hook; - }; - - it('should dispatch getLearningAssistantMessageHistory() with the chat history', () => { - renderTestHook(fakeCourseId, true); - - expect(mockDispatch).toHaveBeenCalledTimes(1); - expect(mockDispatch).toHaveBeenCalledWith(getLearningAssistantMessageHistorySignature); - expect(getLearningAssistantMessageHistory).toHaveBeenCalledWith(fakeCourseId); - }); - - it('should NOT dispatch getLearningAssistantMessageHistory() when disabled', () => { - renderTestHook(fakeCourseId, false); - - expect(mockDispatch).not.toHaveBeenCalled(); - expect(getLearningAssistantMessageHistory).not.toHaveBeenCalled(); - }); - - it('should NOT dispatch getLearningAssistantMessageHistory() with no courseId', () => { - renderTestHook(null, true); - - expect(mockDispatch).not.toHaveBeenCalled(); - expect(getLearningAssistantMessageHistory).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/src/utils/utils.test.jsx b/src/utils/utils.test.jsx index 3edeef44..870c0a04 100644 --- a/src/utils/utils.test.jsx +++ b/src/utils/utils.test.jsx @@ -48,7 +48,9 @@ const createRandomResponseForTesting = () => { message.push(words[Math.floor(Math.random() * words.length)]); } - return { role: 'assistant', content: message.join(' ') }; + const timestamp = new Date(); + + return [{ role: 'assistant', content: message.join(' '), timestamp }]; }; export { renderWithProviders as render, createRandomResponseForTesting }; diff --git a/src/widgets/Xpert.jsx b/src/widgets/Xpert.jsx index cdb99fa2..ce36c6dc 100644 --- a/src/widgets/Xpert.jsx +++ b/src/widgets/Xpert.jsx @@ -1,17 +1,16 @@ import PropTypes from 'prop-types'; import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { getAuthenticatedUser } from '@edx/frontend-platform/auth'; -import { updateSidebarIsOpen, getIsEnabled, getAuditTrial } from '../data/thunks'; +import { updateSidebarIsOpen, getLearningAssistantSummary } from '../data/thunks'; import ToggleXpert from '../components/ToggleXpertButton'; import Sidebar from '../components/Sidebar'; import { ExperimentsProvider } from '../experiments'; -import { useMessageHistory } from '../hooks'; +// import { getLearningAssistantData } from '../hooks'; const Xpert = ({ courseId, contentToolsEnabled, unitId }) => { const dispatch = useDispatch(); - useMessageHistory(courseId); + // getLearningAssistantData(courseId); const { isEnabled, @@ -24,11 +23,8 @@ const Xpert = ({ courseId, contentToolsEnabled, unitId }) => { }; useEffect(() => { - dispatch(getIsEnabled(courseId)); - dispatch(getAuditTrial(courseId)); + dispatch(getLearningAssistantSummary(courseId)); }, [dispatch, courseId]); - console.log("auditTrial:", auditTrial); - console.log("auditTrial.expirationDate:", auditTrial.expirationDate); // NOTE: This value can be used later on if/when we pass the enrollment mode to this componentn const isAuditTrialNotExpired = () => { // eslint-disable-line no-unused-vars diff --git a/src/widgets/Xpert.test.jsx b/src/widgets/Xpert.test.jsx index ca30270c..cb3a99af 100644 --- a/src/widgets/Xpert.test.jsx +++ b/src/widgets/Xpert.test.jsx @@ -9,8 +9,6 @@ import Xpert from './Xpert'; import * as surveyMonkey from '../utils/surveyMonkey'; import { render, createRandomResponseForTesting } from '../utils/utils.test'; import { usePromptExperimentDecision } from '../experiments'; -import { useMessageHistory } from '../hooks'; -// import { updateSidebarIsOpen, getIsEnabled, getAuditTrial } from '../data/thunks'; jest.mock('@edx/frontend-platform/analytics'); jest.mock('@edx/frontend-platform/auth', () => ({ @@ -22,14 +20,6 @@ jest.mock('../experiments', () => ({ usePromptExperimentDecision: jest.fn(), })); -jest.mock('../hooks'); - -// TODO: Fix whatever the heck is going on here. -// jest.mock('../data/thunks', () => ({ -// getIsEnabled: jest.fn(), -// getAuditTrial: jest.fn(), -// })); - const initialState = { learningAssistant: { currentMessage: '', @@ -40,8 +30,6 @@ const initialState = { // I will remove this and write tests in a future pull request. disclosureAcknowledged: true, sidebarIsOpen: false, - - }, }; const courseId = 'course-v1:edX+DemoX+Demo_Course'; @@ -57,12 +45,15 @@ const assertSidebarElementsNotInDOM = () => { beforeEach(() => { const responseMessage = createRandomResponseForTesting(); - jest.spyOn(api, 'fetchChatResponse').mockResolvedValue(responseMessage); - jest.spyOn(api, 'fetchLearningAssistantEnabled').mockResolvedValue({ enabled: true }); - jest.spyOn(api, 'fetchLearningAssistantAuditTrial').mockResolvedValue({ - start_date: '2024-12-02T14:59:16.148236Z', - expiration_date: '9999-12-16T14:59:16.148236Z', + jest.spyOn(api, 'fetchLearningAssistantSummary').mockResolvedValue({ + enabled: true, + message_history: responseMessage, + audit_trial: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', + }, }); + usePromptExperimentDecision.mockReturnValue([]); window.localStorage.clear(); @@ -72,7 +63,7 @@ beforeEach(() => { }); test('doesn\'t load if not enabled', async () => { - jest.spyOn(api, 'fetchLearningAssistantEnabled').mockResolvedValue({ enabled: false }); + jest.spyOn(api, 'fetchLearningAssistantSummary').mockResolvedValue({ enabled: false }); render(, { preloadedState: initialState }); @@ -91,11 +82,6 @@ test('initial load displays correct elements', async () => { // assert that UI elements in the sidebar are not in the DOM assertSidebarElementsNotInDOM(); }); -test('calls useMessageHistory() hook', () => { - render(, { preloadedState: initialState }); - - expect(useMessageHistory).toHaveBeenCalledWith(courseId); -}); test('clicking the call to action dismiss button removes the message', async () => { const user = userEvent.setup(); render(, { preloadedState: initialState }); @@ -181,7 +167,7 @@ test('response text appears as message in the sidebar', async () => { // re-mock the fetchChatResponse API function so that we can assert that the // responseMessage appears in the DOM - const responseMessage = createRandomResponseForTesting(); + const responseMessage = createRandomResponseForTesting()[0]; jest.spyOn(api, 'fetchChatResponse').mockResolvedValue(responseMessage); render(, { preloadedState: initialState }); @@ -330,23 +316,22 @@ test('popup modal should close and display CTA', async () => { expect(screen.queryByTestId('action-message')).toBeVisible(); }); test('survey monkey survey should appear after closing sidebar', async () => { + jest.spyOn(api, 'fetchLearningAssistantSummary').mockResolvedValue({ + enabled: true, + message_history: [ + // A length >= 2 is required to load the survey + { role: 'user', content: 'hi', timestamp: new Date().toString() }, + { role: 'user', content: 'hi', timestamp: new Date().toString() }, + ], + audit_trial: { + start_date: '2024-12-02T14:59:16.148236Z', + expiration_date: '9999-12-16T14:59:16.148236Z', + }, + }); const survey = jest.spyOn(surveyMonkey, 'default').mockReturnValueOnce(1); const user = userEvent.setup(); - const surveyState = { - learningAssistant: { - currentMessage: '', - messageList: [ - { role: 'user', content: 'hi', timestamp: new Date() }, - { role: 'user', content: 'hi', timestamp: new Date() + 1 }, - ], - apiIsLoading: false, - apiError: false, - disclosureAcknowledged: true, - sidebarIsOpen: false, - }, - }; - render(, { preloadedState: surveyState }); + render(); // wait for button to appear await screen.findByTestId('toggle-button'); @@ -357,6 +342,6 @@ test('survey monkey survey should appear after closing sidebar', async () => { await user.click(screen.queryByTestId('close-button')); // assert mock called - expect(survey).toBeCalledTimes(1); + expect(survey).toHaveBeenCalledTimes(1); survey.mockRestore(); });